我需要捕捉一些警告从一些php本机函数抛出,然后处理它们。

具体地说:

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

当DNS查询失败时,它抛出一个警告。

Try /catch不起作用,因为警告不是异常。

我现在有两个选择:

set_error_handler似乎是多余的,因为我必须使用它来过滤页面中的每个警告(这是真的吗?); 调整错误报告/显示,这样这些警告就不会显示在屏幕上,然后检查返回值;如果为假,则没有找到主机名的记录。

这里的最佳实践是什么?


当前回答

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

其他回答

小心使用@操作符——虽然它抑制了警告,但也抑制了致命错误。我花了很多时间调试系统中的一个问题,其中有人写了@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:~$ 

这次我们可以看到为什么它失败了。

通常你不应该使用@,除非这是唯一的解决方案。在这种情况下,应该首先使用dns_check_record函数来了解该记录是否存在。

结合file_get_contents()调用外部url的这几行代码,帮助我更好地处理像“未能打开流:连接超时”这样的警告:

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;
}

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

set_error_handler("warning_handler", E_WARNING);
dns_get_record(...)
restore_error_handler();

function warning_handler($errno, $errstr) { 
// do something
}

如果dns_get_record()失败,它应该返回FALSE,所以你可以用@来抑制警告,然后检查返回值。