2011-05-02 128 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