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

时间:2010-12-10 15:55:18

标签: php error-handling fatal-error

根据the comment on this answer,可以通过使用set_error_handler()无法捕获的shutdown function来捕获致命错误。

但是,我无法确定如何确定是否由于致命错误或脚本到达结束而发生关闭。

此外,调试回溯函数似乎在关闭函数中已经不存在,这使得记录发生致命错误的堆栈跟踪毫无价值。

所以我的问题是:在保持创建正确回溯的能力的同时,对致命错误(特别是未定义的函数调用)作出反应的最佳方法是什么?

4 个答案:

答案 0 :(得分:63)

这对我有用:

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恢复。

至于回溯,你不能...... :(在大多数致命错误的情况下,特别是未定义的函数错误,你真的不需要它。精确定位文件/行发生的地方就足够了。在这种情况下,回溯是无关紧要的。

答案 1 :(得分:9)

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

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()是一个数组,其中包含有关您应该调试的致命错误的所有信息,尽管它没有回溯,如上所述。

通常,如果您的php程序遇到了致命错误(而不是异常),您希望程序爆炸,以便找到并解决问题。我发现register_shutdown_function对于您希望关闭错误报告的生产环境很有用,但是想要某种方法在后台记录错误,以便您可以对其进行响应。如果发生此类错误,您还可以使用该功能将用户定向到友好的html页面,这样您就不会只提供空白页面。

答案 2 :(得分:5)

获取当前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停止显示错误,否则错误文本将在错误处理程序之前发送到客户端

答案 3 :(得分:-2)

我为此使用“ob_start”。

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