2011-05-02 131 views
4

我使用以下函数来设置我自己的错误处理程序和异常处理程序。错误处理程序中抛出的PHP异常不会被异常处理程序捕获

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处理。

但是,如果我在触发错误的同一位置抛出异常,则此异常将由异常处理程序处理。

(希望这是某种可以理解我的意思)

我无言以对这里。 任何想法,我必须寻找问题?

回答

5

这个问题是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. “未定义的变量:富”(E_NOTICE)
  2. “功能名必须是一个字符串”(E_ERROR)

人们会预计errorHandler()赶上E_NOTICE并抛出一个异常,然后由exceptionHandler()处理。由于exceptionHandler()永不返回,执行应该停止在那里。

但是这并不会发生什么:errorHandler()确实被调用并抛出它的异常,但在exceptionHandler()可以作出反应之前,PHP决定由于致命的E_ERROR而退出。

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

UPDATE 2014年4月30日:

这显然已经固定在PHP 5.5(或可能5.4,我现在不能测试)。 $foo$foo()现在的行为方式相同,它们都产生输出exceptionHandler: 'Undefined variable: foo'

+0

尽管我不再在解决这个问题,但您提供了正确的答案并不错。不知何故,这是有道理的,但我没有想到它。谢谢你的答案。 – superbly 2013-10-11 11:30:45

+0

看起来像5.5中修复 - https://3v4l.org/K9NAR – 2015-11-14 16:34:46

+0

,这是没有意义的。为什么PHP应该决定退出E_ERROR,甚至没有达到它? – emfi 2017-07-11 09:58:13

0

我看到了两个可能的原因,为什么你的异常处理程序是没有得到所谓:

  • 没有引发的异常;或
  • 您正在捕捉异常。

这可能是一个例外,是不是养了PHP错误,每例如,如果您提供的第二个参数$error_typesset_error_handler,这会改变什么错误级别自定义处理程序被调用。

更可能的原因是您已经捕获了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); 
} 
+0

其实异常是在错误处理程序中引发的。如果我抛出异常或ErrorException(它扩展了异常btw),则无关紧要,异常处理程序无法捕获ErrorHandler中抛出的异常。 – superbly 2011-05-02 14:51:04

+0

另外,ErrorHandler中引发的异常不会被另一个try catch块捕获。 – superbly 2011-05-02 14:53:12

+1

@shifty:[It works](http://codepad.org/hwbsYcRF)。我的意思是,你显然在那里做错了什么,因为它适合我。 – netcoder 2011-05-02 14:53:17