首页 文章

我可以尝试/发出警告吗?

提问于
浏览
301

我需要从一些php本机函数中捕获一些警告,然后处理它们 .

特别:

array dns_get_record  ( string $hostname  [, int $type= DNS_ANY  [, array &$authns  [, array &$addtl  ]]] )

当DNS查询失败时,它会发出警告 .

try / catch 不起作用,因为警告不是例外 .

我现在有2个选择:

  • set_error_handler 似乎有点矫枉过正,因为我必须使用它来过滤页面中的每个警告(这是真的吗?);

  • 调整错误报告/显示,以便这些警告不会发生't get echoed to screen, then check the return value; if it' s false ,找不到主机名的记录 .

这里的最佳做法是什么?

10 回答

  • 5

    如果 dns_get_record() 失败,则应返回 FALSE ,因此可以使用 @ 禁止警告,然后检查返回值 .

  • 326

    您可能应该尝试完全摆脱警告,但如果这不可能,您可以使用@(即@dns_get_record(...))预先调用该调用,然后使用您可以获得的任何信息来确定是否发生了警告或不 .

  • 122

    真正有效的解决方案是使用 E_WARNING 参数设置简单的错误处理程序,如下所示:

    set_error_handler("warning_handler", E_WARNING);
    dns_get_record(...)
    restore_error_handler();
    
    function warning_handler($errno, $errstr) { 
    // do something
    }
    
  • 2

    我想尝试/捕获警告,但同时保持通常的警告/错误记录(例如在 /var/log/apache2/error.log 中);处理程序必须返回 false . 但是,由于"throw new..."语句基本上会中断执行,因此必须执行"wrap in function"技巧,也在以下讨论:

    Is there a static way to throw exception in php

    或者,简而言之:

    function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) {
        throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
      }
      function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) {
        return false && throwErrorException($errstr, 0, $errno, $errfile, $errline);
        # error_log("AAA"); # will never run after throw
        /* Do execute PHP internal error handler */
        # return false; # will never run after throw
      }
      ...
      set_error_handler('warning_handler', E_WARNING);
      ...
      try {
        mkdir($path, 0777, true);
      } catch (Exception $e) {
        echo $e->getMessage();
        // ...
      }
    

    编辑:仔细检查后,事实证明它不起作用:“ return false && throwErrorException ... ”基本上不会抛出异常,只需登录错误日志;删除“ false && " part, as in " return throwErrorException ... ”,会使异常抛出工作,但不会登录error_log ...我在其他地方看到了这种行为 .

  • 4

    Normaly你永远不应该使用@,除非这是唯一的解决方案 . 在该特定情况下,应首先使用函数dns_check_record来知道记录是否存在 .

  • 0

    Set and restore error handler

    一种可能性是在调用之前设置自己的错误处理程序,并稍后使用 restore_error_handler() 恢复先前的错误处理程序 .

    set_error_handler(function() { /* ignore errors */ });
    dns_get_record();
    restore_error_handler();
    

    您可以构建这个想法并编写一个可重用的错误处理程序,为您记录错误 .

    set_error_handler([$logger, 'onSilencedError']);
    dns_get_record();
    restore_error_handler();
    

    Turning errors into exceptions

    您可以使用 set_error_handler()ErrorException 类将所有php错误转换为异常 .

    set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
        // error was suppressed with the @-operator
        if (0 === error_reporting()) {
            return false;
        }
    
        throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    });
    
    try {
        dns_get_record();
    } catch (ErrorException $e) {
        // ...
    }
    

    使用自己的错误处理程序时需要注意的重要一点是,它将绕过 error_reporting 设置并将所有错误(通知,警告等)传递给错误处理程序 . 您可以在 set_error_handler() 上设置第二个参数以定义要接收的错误类型,或使用错误处理程序内的 ... = error_reporting() 访问当前设置 .

    Suppressing the warning

    另一种可能性是使用@运算符抑制调用,然后检查 dns_get_record() 的返回值 . But I'd advise against this 因触发错误/警告而不被抑制 .

  • 3

    我只建议使用@来抑制警告,当它是直接操作时(例如$ prop = @($ high /($ width - $ depth));跳过除零警告) . 但是在大多数情况下最好处理 .

  • 26

    Be careful with the @ operator - 虽然它可以抑制警告但它也可以抑制致命错误 . 我花了很多时间在系统中调试问题,有人写了 @mysql_query( '...' ) ,问题是mysql支持没有加载到PHP中,它引发了一个无声的致命错误 . 对于那些属于PHP核心的东西来说是安全的,但请小心使用它 .

    bob@mypc:~$ php -a
    Interactive shell
    
    php > echo @something(); // this will just silently die...
    

    没有进一步的输出 - 好运调试这个!

    bob@mypc:~$ php -a
    Interactive shell
    
    php > echo something(); // lets try it again but don't suppress the error
    PHP Fatal error:  Call to undefined function something() in php shell code on line 1
    PHP Stack trace:
    PHP   1. {main}() php shell code:0
    bob@mypc:~$
    

    这次我们可以看出它失败的原因 .

  • -2

    尝试检查它是否返回一些布尔值,然后你可以简单地把它作为一个条件 . 我用oci_execute(...)遇到了这个问题,它使用我的唯一键返回了一些违规行为 .

    ex.
    oci_parse($res, "[oracle pl/sql]");
    if(oci_execute){
    ...do something
    }
    
  • 3

    将这些代码行组合在一个外部URL的 file_get_contents() 调用上帮助我更好地处理“ failed to open stream: Connection timed out ”之类的警告:

    set_error_handler(function ($err_severity, $err_msg, $err_file, $err_line, array $err_context)
    {
        throw new ErrorException( $err_msg, 0, $err_severity, $err_file, $err_line );
    }, E_WARNING);
    try {
        $iResult = file_get_contents($sUrl);
    } catch (Exception $e) {
        $this->sErrorMsg = $e->getMessage();
    }
    restore_error_handler();
    

    此解决方案也适用于对象上下文 . 你可以在函数中使用它:

    public function myContentGetter($sUrl)
    {
      ... code above ...
      return $iResult;
    }
    

相关问题