捕获错误异常,包装致命的PHP错误


Catch ErrorException that wraps a fatal PHP error

在我自制的PHP MVC框架中,我编写了一个小的错误处理程序,它将PHP错误包装在一个异常中,然后抛出它。

class ErrorController extends ControllerAbstract {
    ...
    public static function createErrorException($number, $message = NULL, $file = NULL, $line = NULL, array $context = array()) {
        throw new ErrorException($message, $number, 0, $file, $line);
    }
}

然后使用 set_error_handler() 进行注册。这工作正常,除了致命错误(没有双关语)。 我的自定义错误处理程序仍被调用,但我无法捕获引发的ErrorException

此类错误的一个例子是尝试包含不存在的文件:

    try {
        require 'Controller/NonExistentController.php';
    } catch (ErrorException $exc) {
        echo $exc->getTraceAsString(); // code never reaches this block
    }

调用我的自定义错误处理程序并引发异常,但代码永远不会到达"catch"块。相反,PHP生成HTML(不好!):


警告:未捕获的异常"错误异常"与 消息"要求(控制器/不存在的控制器.php):无法打开流:...

其次:

致命错误:程序::main():需要打开失败 'Controller/NonExistentController.php' (include_path='.:') in ...

我不想尝试从致命错误中恢复,但我确实希望我的代码优雅地退出。在这种情况下,这意味着发回一个指示内部错误的 XML 或 JSON 响应,因为这是一个 REST 应用程序,这是我的客户所期望的。HTML 响应也很可能会破坏客户端应用程序。

我应该以不同的方式做这件事吗?

查看有关require的文档 php.net:

require包含相同,除非失败时,它还会产生致命的E_COMPILE_ERROR级别错误。换句话说,它 将停止脚本,而"包含"仅发出警告 (E_WARNING) 这允许脚本继续。

在您的情况下,您可以在 register_shutdown_function 的帮助下处理致命错误,这需要 PHP 5.2+:

function customFatalHandler() {
  $error = error_get_last();
  if( $error === NULL) {
      return;
  }
  $type   = $error["type"];
  $file = $error["file"];
  $line = $error["line"];
  $message  = $error["message"];
  echo "Error `$type` in file `$file` on line $line with message `$message`"; 
}
register_shutdown_function("customFatalHandler");

这也可能对您有所帮助

  1. error_get_last() 和自定义错误处理程序
  2. 为什么 PHP 没有捕获"找不到类"错误?

抱歉有这么否定的答案,但你(很可能)不能。

PHP 被设计为出于某种奇怪的原因尽可能长时间地运行,你有错别字吗? 默默地将该变量初始化为 null,您将 [] 放在某物后面,如果运算符没有意义,则评估为 null!

这对于错误处理来说格外混乱,就像有 4 个系统不能协同工作一样。PHP 通过"猴子修补"进行一些错误处理,如果您尝试通过抛出来处理错误处理程序中的某些内容,这会导致问题,直到处理程序退出它才会"取消修补"。

使用关闭处理程序,从那里投掷可能会导致巨大的问题!之前咬过我的屁股,我不想谈论它:P

它还定义了PHP中的文件"资源"是否在关闭时关闭的实现,它的创建是为了帮助插件在Web服务器上整理。(因此您可以列出它们的列表)