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

2022-08-30 11:39:27

根据对此答案的评论,可以通过关闭功能捕获致命错误,而使用 .set_error_handler()

但是,我无法确定关闭是由于致命错误还是由于脚本到达其末尾而发生的。

此外,调试回溯跟踪函数似乎在关闭函数中失效,因此记录发生致命错误的堆栈跟踪毫无价值。

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


答案 1

这对我有用:

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中恢复过来。

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


答案 2

使用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页面,这样您就不会只提供空白页。


推荐