既然所有错误都是例外,那么 PHP7 上的 set_error_handler(( 会发生什么?让我认为可以捕获可恢复的错误,但事实似乎并非如此,如下所示:
<?php
$_SERVER['TEST'] = new stdClass;
try {
phpinfo();
} catch (Throwable $e) {}
如果你运行该代码,你将得到这个作为输出:
$_SERVER['argc'] => 1
$_SERVER['TEST'] =>
Recoverable fatal error: Object of class stdClass could not be converted to string in /Users/username/zzz.php on line 6
所以很明显,一个错误正在"发布",但没有抛出一个错误,除非我误解了什么?
在 PHP 7 中,并非所有错误都转换为Throwable
错误。
实际上,文档说:
现在,大多数错误都是通过引发错误异常来报告的。
(强调我的(。最!==全部。
有些错误仍然无法捕获。
有趣的是,在 PHP 7.1 发布之前,您使用的错误消息习惯于说"可捕获的致命错误"而不是"可恢复的致命错误"。
这被报告为一个错误,但开发人员实施的解决方案是将错误字符串从可捕获更改为可恢复以消除误解。
在您正在测试的特定情况下,似乎phpinfo()
举起recoverable error
而不是抛出Error
,因此您不能以这种方式抓住它是有道理的。
尽管如此,并不是所有的希望都消失了。
您可以做的是通过实现自己的错误处理程序将所有错误转换为异常。ErrorException
文档中描述了一个示例:
function exception_error_handler($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
// This error code is not included in error_reporting
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("exception_error_handler");
此示例的巧妙之处在于它考虑了您的错误报告设置,因此只有在您的设置下报告的错误才会作为异常实际抛出。否则,什么都不会发生。
测试您的代码:
<?php
function exception_error_handler($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
// This error code is not included in error_reporting
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("exception_error_handler");
$_SERVER['TEST'] = new stdClass;
try {
phpinfo(INFO_VARIABLES);
} catch (Throwable $e) {echo 'CAUGHT!!!!!!';}
打印以下输出:
$_SERVER['TERM_SESSION_ID'] => w0t1p0:xxx-cxx-xxxxxxx-xxxxx
$_SERVER['SSH_AUTH_SOCK'] => /private/tmp/com.apple.launchd.xxxxxxxx/Listeners
$_SERVER['LC_TERMINAL_VERSION'] => 3.3.2
....
$_SERVER['argc'] => 1
$_SERVER['TEST'] =>
CAUGHT!!!!!!%