3

考虑以下两个 PHP (5.4) 脚本。为什么只在执行脚本 A 时调用回调register_shutdown_function,而不是在执行脚本 B 时调用?

脚本 A

set_error_handler(function() {
    throw new Exception();
});
register_shutdown_function(function() {
    echo "shutdown handler invoked\n";
});

undefined();
// "shutdown handler invoked" IS displayed

脚本 B

set_error_handler(function() {
    throw new Exception();
});
register_shutdown_function(function() {
    echo "shutdown handler invoked\n";
});

$undefined->undefined();
// "shutdown handler invoked" IS NOT displayed
4

2 回答 2

1

这是一个错误——如果注册的可调用对象set_error_handler抛出异常,将不会调用关闭函数。

在这种特殊情况下,会发生以下事件链:

  1. 触发非致命错误(未定义变量:未定义)
  2. 调用用户错误处理程序
  3. 抛出异常
  4. 触发致命错误(在非对象上调用成员函数 undefined())
  5. 由于存在异常,未调用关闭函数

https://bugs.php.net/61767(带有补丁!)和https://bugs.php.net/60909的现有错误报告有更多详细信息。

于 2012-07-17T03:00:19.927 回答
0

这是我发现的。

register_shutdown_function 在退出时被调用。

$未定义->未定义();触发 E_NOTICE 错误,因为 $undefined 未定义为通过 set_error_handler 的变量。如果你调用 throw new Exception,php 出于某种原因在退出时不会触发 register_shutdown_function 处理程序只是崩溃,如果你想抛出异常,也许你可以直接调用你的异常函数。

如果你创建了一个虚拟类并定义了 $undefined,但没有创建一个名为 undefined 的成员函数,它的行为方式与调用 undefined() 的方式相同,如下所示

不明确的(); 触发 E_ERROR 立即退出触发 shutdown_function 处理程序

除了使用错误处理程序来捕获不同类型的错误之外,您还可以在关闭函数中执行此操作:

function shutdown_function_handler(){
    if ($error = error_get_last()){
        switch ($error['type']){
            case E_ERROR:
            case E_USER_ERROR:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
                echo " ERRROR:".$error['message'];
        }
    }
}
于 2012-07-15T09:09:03.483 回答