使用register_shutdown_function()处理PHP中的致命错误

根据对这个答案的评论 ,可以通过使用set_error_handler()无法捕获的closures函数来捕获致命错误。

但是,我找不到如何确定是由于致命错误还是由于脚本到达而导致关机。

此外,在关机function中,debugging回溯函数似乎不存在,使得将堆栈跟踪logging到发生致命错误的地方是毫无价值的。

所以我的问题是:什么是对致命错误(尤其是未定义的函数调用)做出反应的最佳方式,同时保持创build正确的回溯的能力?

这适用于我:

 function shutdown() { $error = error_get_last(); if ($error['type'] === E_ERROR) { // fatal error has occured } } register_shutdown_function('shutdown'); spl_autoload_register('foo'); // throws a LogicException which is not caught, so triggers a E_ERROR 

但是,您可能已经知道,但只是要确保:无法以任何方式从E_ERROR中恢复。

至于回溯,你不能… :(在大多数情况下,一个致命的错误,特别是未定义的函数错误,你并不需要它。找出它发生的文件/行就足够了。回溯是无关紧要的在这种情况下。

使用register_shutdown_function区分致命错误和正确应用程序closures的一种方法是将常量定义为程序的最后一行,然后检查常量是否已定义:

 function fatal_error() { if ( ! defined(PROGRAM_EXECUTION_SUCCESSFUL)) { // fatal error has occurred } } register_shutdown_function('fatal_error'); define('PROGRAM_EXECUTION_SUCCESSFUL', true); 

如果程序到达最后,它不会遇到一个致命错误,所以如果定义了常量,我们就知道不运行该函数。

error_get_last()是一个数组,其中包含有关应该debugging的致命错误的所有信息,尽pipe如前所述,它不会有回溯。

一般来说,如果你的php程序遇到了一个致命的错误(而不是一个例外),你希望程序炸毁,以便find并解决问题。 我发现register_shutdown_function对于你想要报错的生产环境很有用,但是想用某种方法在后台logging这个错误,这样你就可以响应了。 如果发生这样的错误,您也可以使用该函数来引导用户访问友好的HTML页面,以便您不只是提供空白页面。

只是一个很好的技巧来获取当前的error_handler方法=)

 <?php register_shutdown_function('__fatalHandler'); function __fatalHandler() { $error = error_get_last(); //check if it's a core/fatal error, otherwise it's a normal shutdown if($error !== NULL && $error['type'] === E_ERROR) { //Bit hackish, but the set_exception_handler will return the old handler function fakeHandler() { } $handler = set_exception_handler('fakeHandler'); restore_exception_handler(); if($handler !== null) { call_user_func($handler, new ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line'])); } exit; } } ?> 

我也不会注意到,如果你打电话

 <?php ini_set('display_errors', false); ?> 

Php停止显示错误,否则错误文本将在您的error handling程序之前发送到客户端

我用这个“ob_start”。

 function fatal_error_handler($buffer) { if (preg_match("|(Fatal error:)(.+)|", $buffer, $regs) ) { //Your code } return $buffer; } ob_start("fatal_error_handler");