【问题标题】:How do you catch recoverable errors in PHP 7+?如何在 PHP 7+ 中捕获可恢复的错误?
【发布时间】:2020-01-06 23:10:46
【问题描述】:

What happens with set_error_handler() on PHP7 now that all errors are exceptions? 让我认为可以捕获可恢复的错误,但事实并非如此,如下所示:

<?php

$_SERVER['TEST'] = new stdClass;

try {
    phpinfo();
} catch (\Throwable $e) {}

如果您运行该代码,您将得到以下输出:

$_SERVER['argc'] => 1
$_SERVER['TEST'] =>
Recoverable fatal error: Object of class stdClass could not be converted to string in /Users/username/zzz.php on line 6

很明显,“发出”了一个错误,但没有抛出一个错误,除非我误解了什么?

【问题讨论】:

  • 这个Link可以帮助你解决或理解php 7+中新的异常处理程序
  • fatalrecoverable errors 抛出的异常不会在 php7 中扩展 Exception
  • 也请参考link
  • 您是否期望发布的代码会引发错误?为什么?
  • @DhavalPurohit - 我没听懂Exception - 我听懂了Throwable

标签: php exception error-handling


【解决方案1】:

在 PHP 7 中,并非所有错误都转换为 Throwable 错误。

其实docs say:

大多数错误现在通过抛出错误异常来报告。

(强调我的)。大多数 !== 全部。

有些错误仍然无法捕获。

有趣的是,在 PHP 7.1 发布之前,您习惯使用的错误消息是“可捕获的致命错误”而不是“可恢复的致命错误”。

这是reported as a bug,但开发人员实施的解决方案是将错误字符串从Catchable更改为Recoverable以消除误解。

在您正在测试的特定情况下,phpinfo() 似乎引发了 recoverable error 而不是抛出 Error,因此您无法以这种方式捕获它是有道理的。

不过,并不是所有的希望都落空了。

您可以通过实现自己的错误处理程序将所有错误转换为异常。 ErrorException documentation 上描述了一个这样的例子:

function exception_error_handler($severity, $message, $file, $line) {
    if (!(error_reporting() & $severity)) {
        // This error code is not included in error_reporting
        return;
    }
    throw new ErrorException($message, 0, $severity, $file, $line);
}

set_error_handler("exception_error_handler");

此示例的巧妙之处在于它考虑了您的错误报告设置,因此只有在您的设置下报告的错误才会被实际抛出为异常。否则,什么都不会发生。

测试你的代码:

<?php
function exception_error_handler($severity, $message, $file, $line) {
    if (!(error_reporting() & $severity)) {
        // This error code is not included in error_reporting
        return;
    }
    throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("exception_error_handler");

$_SERVER['TEST'] = new stdClass;

try {
    phpinfo(INFO_VARIABLES);
} catch (\Throwable $e) {echo 'CAUGHT!!!!!!';}

打印以下输出:

$_SERVER['TERM_SESSION_ID'] => w0t1p0:xxx-cxx-xxxxxxx-xxxxx
$_SERVER['SSH_AUTH_SOCK'] => /private/tmp/com.apple.launchd.xxxxxxxx/Listeners
$_SERVER['LC_TERMINAL_VERSION'] => 3.3.2
....
$_SERVER['argc'] => 1
$_SERVER['TEST'] =>
CAUGHT!!!!!!%

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 2011-04-28
    相关资源
    最近更新 更多