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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4410632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 12:58:20  来源:igfitidea点击:

Handle fatal errors in PHP using register_shutdown_function()

phperror-handlingfatal-error

提问by ThiefMaster

According to the comment on this answerit is possible to catch Fatal Errors through a shutdown functionwhich cannot be caught using set_error_handler().

根据这一答案的评论,可以通过捕捉致命错误关机功能无法使用被捕获set_error_handler()

However, I couldn't find out how to determine if the shutdown has occured due to a fatal error or due to the script reaching its end.

但是,我无法确定如何确定关闭是由于致命错误还是由于脚本结束。

Additionally, the debug backtrace functions seem to be defunct in the shutdown function, making it pretty worthless for logging the stack trace where the Fatal Error occured.

此外,调试回溯功能似乎在关闭功能中已失效,这使得记录发生致命错误的堆栈跟踪变得毫无价值。

So my question is: what's the best way to react on Fatal Errors (especially undefined function calls) while keeping the ability to create a proper backtrace?

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

回答by netcoder

This works for me:

这对我有用:

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

However, you probably know it already, but just to make sure: you can't recover from a E_ERROR in any way.

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

As for the backtrace, you can't... :( In most cases of a fatal error, especially Undefined functionerrors, you don't really need it. Pinpointing the file/line where it occured is enough. The backtrace is irrelevant in that case.

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

回答by Gabriel

One way to distinguish between fatal error and proper application shutdown with the register_shutdown_function is to define a constant as the last line of your program, and then check if the constant is defined:

使用 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);

If the program reaches the end, it could not have encountered a fatal error, so we know not to run the function if the constant is defined.

如果程序到达末尾,它不可能遇到致命错误,因此我们知道如果定义了常量就不要运行该函数。

error_get_last() is an array with all the information regarding the fatal error that you should need to debug, though it will not have a backtrace, as has been mentioned.

error_get_last() 是一个数组,其中包含有关您应该需要调试的致命错误的所有信息,尽管如前所述,它没有回溯。

Generally, if your php program has encountered a fatal error (as opposed to an exception), you want the program to blow up so you can find and fix the problem. I've found register_shutdown_function useful for production environments where you want error reporting off, but want some way to log the error in the background so that you can respond to it. You could also use the function to direct the user to a friendly html page in the event of such an error so that you don't just serve up a blank page.

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

回答by Sander Visser

Just a nice trick to get the current error_handler method =)

获取当前 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;
    }
}
?>

Also i wan't to note that if you call

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

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

Php stops displaying the error, otherwise the error text will be send to the client prior to your error handler

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

回答by gs-design

I use "ob_start" for this.

为此,我使用“ob_start”。

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