在错误处理程序中抛出的PHP异常不会被异常处理程序捕获


PHP exceptions thrown in error handler are not caught by exception handler

我使用下面的函数来设置我自己的错误处理程序和异常处理程序。

set_error_handler
set_exception_handler

错误处理程序将错误转换为异常。(抛出一个新的异常)

但是这些异常不会被我自己的异常处理程序捕获。

错误处理程序示例:

function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
   throw new Exception("this was an error");
}

异常处理程序示例:

function exceptionHandler($e){
   // don't get here when exception is thrown in error handler
   Logger::logException($e); 
}

(I think this cannot work anyway)

应该这样做吗?

或者有人能解释一下为什么它不能工作吗?

编辑:

我做了一些测试,应该可以。

ErrorHandler中抛出的异常被ExceptionHandler捕获在ExceptionHandler中触发的错误被ErrorHandler处理

仅供参考。

My Problem have to other other


编辑:

我仍然没有发现为什么errorHandler中抛出的异常没有被我的exceptionHandler捕获。

例如,当我在代码的某个地方有这个

trigger_error("this is an error"); // gets handled by the errorHandler
throw new Exception("this is an exception"); // gets handler by the exceptionHandler

错误会被errorHandler处理,但是errorHandler中抛出的异常不会被exceptionHandler处理。

但是,如果在触发错误的地方抛出异常,则异常处理程序将处理该异常。

(希望你能理解我的意思)

我一点头绪都没有。有什么想法吗,我要找的问题?

OP观察到错误处理程序抛出的一些异常不能被捕获,这实际上是正确的:

function errorHandler($errno, $errstr, $errfile, $errline) {
    throw new Exception($errstr);
}
function exceptionHandler($e) {
    echo "exceptionHandler: '", $e->getMessage(), "''n";
}
set_error_handler("errorHandler");
set_exception_handler("exceptionHandler");
// this works as expected
$a = $foo;
// this does not
$a = $foo();

在最后一行中,实际上连续触发了两个错误:

  1. 未定义变量:foo" (E_NOTICE)
  2. "函数名必须是字符串" (E_ERROR)

可以期望errorHandler()捕获E_NOTICE并抛出异常,然后由exceptionHandler()处理。由于exceptionHandler()永远不会返回,执行应该停止在那里。

但事实并非如此:errorHandler()确实被调用并抛出异常,但在exceptionHandler()可以做出反应之前,PHP决定退出,因为致命的E_ERROR。

这很不幸,而且据我所知没有通用的解决方案。您可以做的一件事是不从错误处理程序中调用throw new Exception(...),而是直接调用exceptionHandler(new Exception(...))。这可以像预期的那样工作,但缺点是您不能再try .. catch PHP错误了。

更新2014-04-30:

这显然已经在PHP 5.5中修复了(或者可能是5.4,我现在无法测试)。$foo$foo()现在的行为方式相同,它们都产生输出exceptionHandler: 'Undefined variable: foo'

我看到两个可能的原因,为什么你的异常处理程序没有被调用:

  • 没有异常;或
  • 您正在捕获异常。

如果您为set_error_handler提供第二个参数$error_types,则有可能不会为PHP错误引发异常,这改变了应该调用自定义处理程序的错误级别。

更可能的原因是您已经在try...catch块中捕获了异常。自定义异常处理程序仅在未捕获的异常:

时调用
function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
   throw new Exception("this was an error");
}
function exceptionHandler($e) {
   echo 'exceptionHandler';
}
set_error_handler('errorHandler');
set_exception_handler('exceptionHandler');
try {
    file_get_contents('foo');
} catch (Exception $e) {
    echo $e->getMessage(); // exceptionHandler() not called
}
file_get_contents('foo');  // exceptionHandler() is called

我还建议您看一下内置的ErrorException类:

function errorHandler($errno, $errstr, $errfile, $errline) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}