Can I try/catch a warning?
我需要捕获一些来自PHP本机函数的警告,然后处理它们。
明确地:
1 |
当DNS查询失败时,它会发出警告。
我现在有两个选择:
调整错误报告/显示,使这些警告不会回显到屏幕上,然后检查返回值;如果是
这里的最佳实践是什么?
设置和还原错误处理程序
一种可能是在调用之前设置自己的错误处理程序,然后使用
1 2 3 |
您可以基于这个想法,编写一个可重用的错误处理程序,为您记录错误。
1 2 3 |
将错误转化为异常
可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) { // ... } |
在使用自己的错误处理程序时需要注意的一点是,它将绕过
取消警告
另一种可能是使用@operator抑制调用,然后检查
实际可行的解决方案是使用
1 2 3 4 5 6 7 | set_error_handler("warning_handler", E_WARNING); dns_get_record(...) restore_error_handler(); function warning_handler($errno, $errstr) { // do something } |
当心
1 2 3 4 | bob@mypc:~$ php -a Interactive shell php > echo @something(); // this will just silently die... |
没有进一步的输出-祝您调试顺利!
1 2 3 4 5 6 7 8 | 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:~$ |
这一次我们可以看到失败的原因。
我想尝试/捕捉一个警告,但同时保留通常的警告/错误日志(例如在
有静态方法可以在PHP中引发异常吗
或者,简而言之:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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(); // ... } |
编辑:经过仔细检查,发现它不起作用:"
您可能应该尝试完全消除警告,但如果不可能,您可以使用@(即@dns_get_record(…))预先结束呼叫,然后使用您可以得到的任何信息来确定警告是否发生。
将这些代码行与对外部URL的
1 2 3 4 5 6 7 8 9 10 | 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(); |
这个解决方案也适用于对象上下文。您可以在函数中使用它:
1 2 3 4 5 | public function myContentGetter($sUrl) { ... code above ... return $iResult; } |
正常情况下,除非这是唯一的解决方案,否则不应使用@。在这种特定情况下,应该首先使用函数dns_check_record来了解该记录是否存在。
如果
尝试检查它是否返回一些布尔值,然后您可以简单地将其作为一个条件。我在oci_execute(…)中遇到了这个问题,它使用我的唯一键返回了一些冲突。
1 2 3 4 5 | ex. oci_parse($res,"[oracle pl/sql]"); if(oci_execute){ ...do something } |
我只建议在直接操作时使用@来禁止警告(例如$prop=@($high/($width-$depth));跳过零警告的除法)。不过,在大多数情况下,最好处理。