這篇文章介紹的內容是關於PHP7錯誤異常層級,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
PHP 7 錯誤異常層級
探究 PHP 7 的異常階層
在過去的 PHP 中,幾乎不可能會去處理致命錯誤。致命錯誤只會輕易的終止指令碼執行,而不會調用 set_error_hander() 錯誤處理程式。
在 PHP 7 中,當致命或是可恢複性錯誤 (E_ERROR and E_RECOVERABLE_ERROR) 發生時,異常會被捕獲,而不是中止指令碼。在特定的情況下,還是存在會致命的錯誤,比如記憶體不足之類,也會像之前一樣立即中止指令碼。PHP 7 中未捕獲的異常依舊時致命錯誤。這意味著,如果 PHP 5.x 中未捕獲的異常,在 PHP 7 中依舊是致命錯誤。
注意,例如警告或是通知錯誤在 PHP 7 中保持不變,只有致命錯誤或是可恢複性錯誤會拋出異常。
致命或是可恢複性錯誤的拋出並不延伸自 Exception 類。這種分離是為了防止現存的 PHP 5.x 代碼接收到的錯誤異常調用到終止程式。致命或是可恢複錯誤拋出的異常將執行個體化一個新的異常類:Error。和其他異常類相同,被捕獲到的 Error 類將會在最後一個程式塊執行完畢之後再行處理。
相較於 PHP 7 alpha-2 之前,PHP 7 的異常類層次有所不同, 被拋出的致命和可恢複性的錯誤將於 EngineException 類執行個體化,而 EnginException 類並不繼承於 Exception。Exception 和 EngineException 都繼承於 BaseException。
Throwable
為了聯合這兩個異常分支,Exception 和 Error 都實現了一個新的介面,Throwable。
PHP 7 中新的異常層次如下:
Throwable //(介面) |- Exception implements Throwable |- ... |- Error implements Throwable |- TypeError extends Error |- ParseError extends Error // 編譯時間錯誤 |- ArithmeticError extends Error |- pisionByZeroError extends ArithmeticError |- AssertionError extends Error
如果在 PHP 7 中定義 Throwable 介面,那應該和下面的代碼相近。
interface Throwable{ public function getMessage(): string; public function getCode(): int; public function getFile(): string; public function getLine(): int; public function getTrace(): array; public function getTraceAsString(): string; public function getPrevious(): Throwable; public function __toString(): string;}
這個介面應當很熟悉。Throwable 特定的方法和 Exception 的相同。唯一不同的是 Throwable::getPrevious() 會返回 Throwable Exception 和 Error 類的建構函式都將接收一個 Throwable 的執行個體作為先前的異常。
Throwable 可以在 try/catch 塊中用老捕獲異常或是錯誤對象(將來可能可以捕獲更多的異常類型)。記住,這裡更建議捕獲更為具體的異常類,並採取相應的處理措施。然而,在一些場合下,需要寬泛的捕獲異常(比如日誌或是架構的錯誤處理)。在 PHP 7 中,這些異常捕獲塊更適合使用 Throwable 而不是 Exception。
try { // Code that may throw an Exception or Error.} catch (Throwable $t) { // Handle exception}
自訂類不能實現 Throwable 外掛程式,這個部分由於可預見性和一致性:只有執行個體化 Excetion 和 Error 類才能拋出異常。此外,異常攜帶了棧中被建立的對象的資訊。自訂類並未自動擁有儲存資訊的參數。
Throwable can be extended to create package-specific interfaces or add additional methods. 只有繼承了 Exception 或是 Error 的類才可以實現拓展了 Throwable 的外掛程式。
interface MyPackageThrowable extends Throwable {}class MyPackageException extends Exception implements MyPackageThrowable {}throw new MyPackageException();
Error
在 PHP 5.下版本中所有的 errors 都是致命錯誤或是可恢複性致命錯誤,而在 PHP 7 中都拋出 Error 的執行個體化。像其他異常 Error 對象可以通過 try/catch 程式塊捕獲。
$var = 1;try { $var->method(); // Throws an Error object in PHP 7.} catch (Error $e) { // Handle error}
通常,之前的致命錯誤都將拋出 Error 基類的執行個體化,但是一些錯誤會拋出更加確切的 Error 子類:TypeError, ParseError, and AssertionError。
TypeError (類型錯誤)
TypeError 執行個體化的拋出是由實參和形參 當調用函數時申明的形參和實參類型不一致(傳入參數和方法中定義的參數類型不一致)將會拋出一個 TypeError 執行個體。
function add(int $left, int $right){ return $left + $right;}try { $value = add('left', 'right');} catch (TypeError $e) { echo $e->getMessage(), "\n";}
得到的輸出:
Argument 1 passed to add() must be of the type integer, string given
ParseError (解析錯誤)
included/required 檔案,或者 eval() 中的程式碼封裝含語法錯誤時,ParseError 將會被拋出。
try { require 'file-with-parse-error.php';} catch (ParseError $e) { echo $e->getMessage(), "\n";}
ArithmeticError (算數錯誤)
拋出 ArithmeticError 錯誤有兩種情況:負數位移,或者使用 PHP_INT_MIN 當作分子,-1 做分母調用 intp()(PHP_INI_MIN / -1 傳回值是浮點型)。
try { $value = 1 << -1;} catch (ArithmeticError $e) { echo $e->getMessage(), "\n";}
pisionByZeroError (分母為零)
分母為零時使用 intp() 或者取餘(%) 會拋出 pisionByZeroError 錯誤。注意,除零隻會引起一個警告,計算結果為 NaN。
try { $value = 1 % 0;} catch (pisionByZeroError $e) { echo $e->getMessage(), "\n";}
AssertionError (斷言)
當不滿足 assert() 設定的條件時,將會拋出一個 AssertionError 錯誤。
ini_set('zend.assertions', 1);ini_set('assert.exception', 1);$test = 1;assert($test === 0);
不滿足 assert() 設定的條件,拋出一個 AssertionError 錯誤,並且 assert.exception = 1,異常輸出如下:
Fatal error: Uncaught AssertionError: assert($test === 0)
assert() is only executed and will only throw an AssertionError if assertions are enabled and set to throw exceptions with ini settings zend.assertions = 1 and assert.exception = 1.
使用 Error
使用者可以建立自己的 Error 類,作為 Error 基類的拓展。這可能帶來重要的問題:什麼場合下應該拋出一個 Exception 類的子類執行個體,什麼場合下又應該拋出 Error 類的子類執行個體?
由於錯誤對象不應當在程式運行中處理,捕獲錯誤對象應當是少見的。通常而言,錯誤對象應當捕獲並記錄之,執行必要的清理,並給使用者展示錯誤資訊。
編寫相容 PHP 5.x 和 7 Exceptions 類的代碼
在 PHP 5.x 和 7 使用相同的代碼捕獲異常,可以實用多重捕獲代碼塊,首先捕獲 Throwable,之後時 Exception。一旦不需要維護 PHP 5.x 的系統,代碼塊可以立刻被清理掉。
try { // Code that may throw an Exception or Error.} catch (Throwable $t) { // Executed only in PHP 7, will not match in PHP 5.x} catch (Exception $e) { // Executed only in PHP 5.x, will not be reached in PHP 7}
英文原文: trowski.com/2015
本文雖拙,卻也系作者勞動,轉載還請保留本文連結: http://cyleft.com/?p=721