我需要捕捉一些警告从一些php本机函数抛出,然后处理它们。
具体地说:
array dns_get_record ( string $hostname [, int $type= DNS_ANY [, array &$authns [, array &$addtl ]]] )
当DNS查询失败时,它抛出一个警告。
Try /catch不起作用,因为警告不是异常。
我现在有两个选择:
set_error_handler似乎是多余的,因为我必须使用它来过滤页面中的每个警告(这是真的吗?);
调整错误报告/显示,这样这些警告就不会显示在屏幕上,然后检查返回值;如果为假,则没有找到主机名的记录。
这里的最佳实践是什么?
我想尝试/捕捉一个警告,但同时保持通常的警告/错误日志(例如在/var/log/apache2/error.log);处理程序必须返回false。然而,由于"throw new…"语句基本上会中断执行,因此必须使用"wrap in function"技巧,也在下面讨论过:
在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 &&"部分,如在"return throwErrorException…"中,将使异常抛出工作,但将不会记录error_log…尽管如此,我仍然会把这篇文章贴在网上,因为我还没有在其他地方看到这种行为的记录。
设置和恢复错误处理程序
一种可能是在调用之前设置自己的错误处理程序,然后使用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();
将错误转化为异常
您可以使用set_error_handler()和ErrorException类将所有php错误转换为异常。
set_error_handler(function($errno, $errstr, $errfile, $errline) {
// 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()。
抑制警告
另一种可能是使用@操作符抑制调用,然后检查dns_get_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;
}