PHP 的異常處理、錯誤的拋出及錯誤回調函數

1、錯誤、異常 等級常量表 php

error:不能在編譯期發現的運行期錯誤,不如試圖用 echo 輸出一個未賦值的變量,這類問題每每致使程序或邏輯沒法繼續下去而須要中斷; 數組

exception:程序執行過程當中出現意料以外的狀況,邏輯上每每是行得通的,但不符合應用場景,好比接收到一個長度超出預約格式的用戶命名,所以,異常主要靠編碼人員作預先作判斷後拋出,捕獲異常後改變程序流程來處理這些狀況,沒必要中斷程序。 函數

 PHP 對於異常和錯誤的界定彷佛不是很明顯,尤爲是低版本的PHP。 this

錯誤和日誌記錄值    常量                            說明                                              備註
1                  E_ERROR (integer)     致命的運行時錯誤。          |這類錯誤通常是不可恢復的狀況,例如內存分配致使的問題。後果是致使腳本終止再也不繼續運行。   編碼

2                  E_WARNING (integer)   運行時警告 (非致命錯誤)。  |僅給出提示信息,可是腳本不會終止運行。   spa

4                  E_PARSE (integer)     編譯時語法解析錯誤。          |解析錯誤僅僅由分析器產生。   代理

8                  E_NOTICE (integer)   運行時通知。                   |表示腳本遇到可能會表現爲錯誤的狀況,可是在能夠正常運行的腳本里面也可能會有相似的通知。   日誌

16                E_CORE_ERROR(integer)   PHP初始化啓動過程當中發生的致命錯誤。  |該錯誤相似 E_ERROR,可是是由PHP引擎核心產生的。 since PHP 4 code

32                E_CORE_WARNING(integer)   PHP初始化啓動過程當中發生的警告 (非致命錯誤) 。 |相似 E_WARNING,可是是由PHP引擎核心產生的。 since PHP 4 對象

64                E_COMPILE_ERROR(integer)   致命編譯時錯誤。          |相似E_ERROR, 可是是由Zend腳本引擎產生的。 since PHP 4

128              E_COMPILE_WARNING(integer)    編譯時警告 (非致命錯誤)。  |相似 E_WARNING,可是是由Zend腳本引擎產生的。 since PHP 4

256              E_USER_ERROR(integer)       用戶產生的錯誤信息。        |相似 E_ERROR, 可是是由用戶本身在代碼中使用PHP函數 trigger_error()來產生的。 since PHP 4

512              E_USER_WARNING(integer)   用戶產生的警告信息。         |相似 E_WARNING, 可是是由用戶本身在代碼中使用PHP函數 trigger_error()來產生的。 since PHP 4

1024            E_USER_NOTICE(integer)   用戶產生的通知信息。        |相似 E_NOTICE, 可是是由用戶本身在代碼中使用PHP函數 trigger_error()來產生的。 since PHP 4

2048            E_STRICT (integer)         啓用 PHP 對代碼的修改建議。       |確保代碼具備最佳的互操做性和向前兼容性, since PHP 5

4096            E_RECOVERABLE_ERROR(integer)   可被捕捉的致命錯誤。   |它表示發生了一個可能很是危險的錯誤,可是尚未致使PHP引擎處於不穩定的狀態。 若是該錯誤沒有被用戶自定義句柄捕獲 (參 見 set_error_handler()),將成爲一個 E_ERROR 從而腳本會終止運行。 since PHP 5.2.0

8192            E_DEPRECATED(integer)        運行時通知。               |啓用後將會對在將來版本中可能沒法正常工做的代碼給出警告。 since PHP 5.3.0

16384          E_USER_DEPRECATED(integer)    戶產少的警告信息。   |相似 E_DEPRECATED, 可是是由用戶本身在代碼中使用PHP函數 trigger_error()來產生的。 since PHP 5.3.0

30719          E_ALL (integer)               E_STRICT出外的全部錯誤和警告信息。    

*30719 in PHP 5.3.x, 6143 in PHP 5.2.x, 2047 previously

2、error_reporting() 及 try-catch、thrown 

error_reporting() 函數能夠獲取(不傳參時)、設定腳本處理哪些異常(並不是全部異常都須要處理,例如 E_CORE_WARNING、E_NOTICE、E_DEPRECATED 是能夠忽略的),該設定將覆蓋 php.ini 中 error_reporting 選項定義的異常處理設定。

例如:

error_reporting(E_ALL&~E_NOTICE) ; // 除了E_NOTICE其餘異常都會被觸發 //(E_ALL&~E_NOTICE 的二進制運算結果是:E_NOTICE對應位的值被設置爲0,應注意到, //錯誤和日誌記錄值都是一個二進制數,某一位設置爲1)

try-catch 沒法在類的自動加載函數 __autoload() 內生效。

try-catch 用於捕獲異常,沒法捕獲錯誤,例如 trigger_error() 觸發的錯誤,異常和錯誤是不同的。

try{  
// you codes that maybe cause an error  
}catch(Exception $err){  
// 這個錯誤對象須要聲明類型, Exception 是系統默認異常處理類     
echo $err->getMessage();
} 
//thrown 能夠拋出一個異常,如:  //thrown new Exception('an error');

一個例子:

try {      
 if ( empty( $var1 ) )         
   throw new NotEmptyException();      
 if ( empty( $var2 ) )          
  throw new NotEmptyException();      
 if ( ! preg_match() )          
   throw new InvalidInputException();     
 $model->write();      
 $template->render( 'success' ); 
} catch ( NotEmptyException $e ) {      
  $template->render( 'error_empty' );
} catch ( InvalidInputException $e ) {      
  $template->render( 'error_preg' );
}

Exception 類的結構:其中大部分方法都是 禁止改寫的(final )

Exception {
/* 屬性 */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* 方法 */
public __construct ([ string $message = "" [, int $code = 0 [, Exception $previous = null]]] )
final public string getMessage ( void ) //異常拋出的信息
final public Exception getPrevious ( void ) //前一異常
final public int getCode ( void ) //異常代碼,這是用戶自定義的
final public string getFile ( void ) //發生異常的文件路勁
final public int getLine ( void ) //發生異常的行
final public array getTrace ( void ) //異常追蹤信息(array)
final public string getTraceAsString ( void ) //異常追蹤信息(string)
public string __toString ( void ) //試圖直接 將異常對象看成字符串使用時調用子函數的返回值
final private void __clone ( void ) //克隆異常對象時調用
}

擴展異常類

try-catch 能夠有多個 catch 子句,從第一個 catch 子句開始,若是子句內的 異常變量 類型匹配 thrown 語句拋出 的異常類型,則該子句會被執行而再也不執行其餘catch子句,不然繼續嘗試下一個 catch 子句,因爲Exception 是全部 異常類的基類,因 此拋出的異常都會與他匹配 ,若是須要根據不一樣異常類型使用不一樣的處理方法,應該將 Exception 類型的 catch 子句放到最後。 

Exception 是全部異常的基類,能夠根據實際須要擴展異常類

calss MyException extends Exception{      
    public errType = 'default';     
    public function __construct($errType=''){      
    $this->errType = $errType;
}

} try{ 
   // you codes that maybe cause an error     
   thrown new MyException('an error');
}catch(MyException $err){      
   // 這個錯誤對象須要聲明類型       
   echo $err->errType(); 
}catch(ErrorException $err){      
   //ErrorException 是 PHP 5 增長的異常類以便將錯誤封裝爲異常,能夠更好地處理錯誤信息,繼承於 Exception     
   echo 'error !'; 
}catch(Exception $err){
   redirect('/error.php');
 }

你可能會在 catch 子句中判斷異常的類型,或者根據 code 等信息來決定是否處理異常,若是你寫在 catch 子句的代碼沒法適當的處理捕獲的異常,你能夠在 catch 子句內繼續 拋出異常。

三 、 Exception 異常的回調函數


set_exception_handler('exceptionHandlerFun')     //發生 Exception 或其 子類的 異常是會調用此函數      
function exceptionHandlerFun($errObj){      
   // Exception 異常的回調函數 只有一個參數,就是拋出的異常對象。
     //.......  
}

 Exception 異常的回調函數並不能像  set_error_handler 的回調函數那樣經過返回 true 來使異常被消除,即便 回調函數處理了異常,後繼代碼也不會被繼續執行,所以想繼續執行後續代碼必須使用 try-catch,在 try-catch 內被捕獲的異常不會觸發 exception_handler

可是有一個例外:拋出的異常即便沒有被處理,腳本結束回調函數能夠被執行。

register_shutdown_function(callback functionName[,argument1,argument2,...]);

例如:

function shutdownfunction(){      
    echo 'script is end';
}  
register_shutdown_function("shutdownfunction"); 

由於 shutdownfunction() 在腳本結束時被執行,因此 這個回調函數以內能夠調用腳本中任意位置的函數,即便該函數定義在 錯誤拋出位置以後(函數定義是在 腳本編譯期完成的)。

4、trigger_error(string errorMsg[,int user_error_type]) 

 該函數用於主動觸發一個錯誤: user_error_type 只能是 E_ALL、E_USER_ERROR、 E_USER_WARNING、 E_USER_NOTICE 或其組合的值。

註冊 error (包括系統拋出的 Error 和 用戶拋出的 Error )的處理函數和消除 error:

set_error_handler(callback functionName[,user_error_type]); 
// 爲 trigger_error() 設置一個回調函數來處理錯誤,包括系統拋出的錯誤和用戶使用 
//trigger_error() 函數觸發的錯誤。

可選參數 user_error_type :

若是設定此參數,則 trigger_error 拋出的錯誤類型符合 在user_error_type 的定義範圍才能觸發回調函數。

這個值的設置相似於 error_reporting() 函數 。

第一個參數(callbeck functionName):

一個函數名,該函數 能夠有 5 個參數,其中前 2 個必選,依次是:

trigger_error 拋出的 user_error_type、trigger_error 拋出的 errorMsg、拋出錯誤的文件的 絕對路勁、拋出錯誤的行號、拋出錯誤時的上下文環境 (一個數組,包含了trigger_error() 所在做用域內的全部變量、函數、類等數據 )

回調函數的返回值: 若是返回 false ,系統錯誤處理機制仍然繼續拋出該錯誤,返回 true 或 無返回值 則消除錯誤。

你可使用 set_error_handler() 來將 PHP 程序 拋出的錯誤代理給 ErrorException使錯誤能夠相似異常那樣顯示:

function error_handler($errorType, $errorMsg, $errorFile, $errorLine ) {      
    echo '<div style="color:red;">error_handler is called!</div>';      
    throw new ErrorException($errorMsg, 0, $errorType, $errorFile, $errorLine);
} 
set_error_handler('error_handler'); count();

 用戶使用 trigger_error()  觸發的錯誤不會被 try-catch 異常捕獲語句捕獲。

相關文章
相關標籤/搜索