【问题标题】:PHP exceptions thrown in error handler are not caught by exception handler错误处理程序中抛出的 PHP 异常不会被异常处理程序捕获
【发布时间】:2011-08-17 00:18:40
【问题描述】:

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

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); 
}

(我认为这无论如何都行不通)

这应该工作吗?

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

编辑:

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

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

仅供参考。

我的问题必须在别处


编辑:

我仍然没有找到为什么我的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处理。

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

(希望我的意思可以理解)

我在这里一无所知。 我必须寻找问题的任何想法?

【问题讨论】:

    标签: php


    【解决方案1】:

    这个问题已经超过 2 年了,但是 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() 做出反应之前,由于致命的 E_ERROR,PHP 决定退出。

    很不幸,我知道没有非常通用的解决方案。您可以做的一件事是不要在错误处理程序中使用throw new Exception(...),而是直接调用exceptionHandler(new Exception(...))。这可以按预期工作,但缺点是您不能再出现try .. catch PHP 错误。

    2014 年 4 月 30 日更新:

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

    【讨论】:

    • 即使我不再处理这个问题,很高兴你提供了正确的答案。不知何故,这样说有道理,但我没有考虑过。谢谢你的回答。
    • 这没有意义。为什么 php 甚至没有到达 E_ERROR 就决定退出?
    【解决方案2】:

    我发现您的异常处理程序没有被调用的两个可能原因:

    • 没有引发异常;或
    • 您遇到了异常。

    例如,如果您将第二个参数 $error_types 提供给 set_error_handler,则可能不会针对 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);
    }
    

    【讨论】:

    • 实际上异常是在错误处理程序中抛出的。不管我是抛出异常还是 ErrorException(顺便说一句,它扩展了异常),ErrorHandler 中抛出的异常不会被异常处理程序捕获。
    • 另外,ErrorHandler 中抛出的异常没有被另一个 try catch 块捕获。
    • @shifty:It works。我的意思是,你显然在那里做错了什么,因为它对我来说很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 2018-03-23
    相关资源
    最近更新 更多