error_reporting = E_ALL | E_STRICT display_errors = Off
我设置error_reporting来报告所有内容,我使用自定义错误处理程序来抛出异常.我的期望是display_errors = Off将防止显示任何错误消息.
无论如何,当发生致命错误时,会绕过自定义错误处理程序(因为脚本执行立即停止),并且执行关闭处理程序.
现在,关于我的简化代码:
error_reporting(E_ALL | E_STRICT); ini_set('display_errors','Off'); function shutdown_handler() { $err = error_get_last(); $fatal = array(E_ERROR,E_PARSE,E_CORE_ERROR,E_COMPILE_ERROR); if ($err && in_array($err['type'],$fatal)) { echo "\n\ntest fatal error output\n\n"; } exit(); } register_shutdown_function('shutdown_handler');
要测试它,我会生成一个“允许的内存大小耗尽”致命错误,如下所示:
// max out available memory $data = ''; while(true) { $data .= str_repeat('#',PHP_INT_MAX); }
因为我有display_errors = Off我期望这只产生以下输出(根据关闭处理程序):
test fatal error output
而是我继续接受:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2147483648 bytes) in /home/daniel/mydev/PHP/test0.PHP on line 24 PHP Stack trace: PHP 1. {main}() /home/daniel/mydev/PHP/test0.PHP:0 PHP 2. str_repeat() /home/daniel/mydev/PHP/test0.PHP:24 test fatal error output
结论
正如@Cthos所说的那样,“E_ERROR和display_errors不能很好地在一起玩”.
E_PARSE也是如此(我假设E_CORE_ERROR / E_COMPILE_ERROR,但是我没有打破我的PHP安装来测试它).我想这是有道理的,PHP会强制错误追溯到STDOUT在这些情况下,因为如果你不可能永远不知道/为什么事情出错了.
所以在这种情况下的解决办法是:
> as @Cthos建议,使用PHP.ini:error_reporting =(E_ALL&〜E_ERROR)或在运行时使用error_reporting(E_ALL&〜E_ERROR)静音E_ERROR通知;
>更新关闭处理程序以检查最后一个错误是否为E_ERROR类型,如果是,则执行相应的操作.
至于像E_PARSE,E_CORE_ERROR等其他致命的事情,你只需要确保你的代码是正确的,你的PHP可以工作.如果您尝试沉默E_PARSE错误并在关闭功能中处理它们将无法正常工作,因为解析错误会阻止PHP发生这种变化.
所以,更新/工作的关机处理程序如下所示:
error_reporting(E_ALL & ~ E_ERROR); function shutdown_handler() { $err = error_get_last(); if ($err && $err['type'] == E_ERROR) { $msg = 'PHP Fatal Error: '.$err['message'].' in '.$err['file']. ' on line '.$err['line']; echo $msg,PHP_EOL; } exit(); }
log_errors
和
error_log
)而完全独立于display_errors配置.从命令行运行脚本时,默认的PHP.ini配置会将错误详细信息记录到stderr.在Apache下,它们显示在
/etc/httpd/logs/error_log
.
查看PHP源的main.c中的php_error_cb
函数.特别地,第1056行清楚地表明,任何格式为“PHP%s:%s在%s行%d”上的消息都是由于错误记录配置(由于display_errors的错误信息将不会有“PHP:”)字首).