1. 程式人生 > 其它 >PHP異常處理(Exception)

PHP異常處理(Exception)

異常(Exception)處理用於在指定的錯誤發生時改變指令碼的正常流程,是在PHP5 中的增加的一個重要特性。異常處理是一種可擴充套件、易維護的錯誤處理統一機制,並提供了一種新的面向物件的錯誤處理方式。

JavaC#Python等語言中很早就提供了這種異常處理機制,如果你對哪一種語言中的異常處理熟悉,那對 PHP 中提供的異常處理機制也就不會陌生了。

異常處理的加入使得在 PHP 程式中排查錯誤、捕獲異常更加簡單容易,也使得 PHP 程式在健壯性方面有很大改善和提高。異常處理在 PHP 中的具體體現就是,PHP 提供了一個名叫 Exception 的類完成對 PHP 程式異常的處理,這個類包含了一些處理異常的函式,這些函式可以捕獲程式異常和錯誤。

本節我們就來介紹一下 PHP 中的異常處理類及類函式的用法。

PHP 中的異常處理類

PHP 中提供了內建的異常處理類——Exception,該類中常用的成員函式如下所示:

  • getMessage():返回異常的訊息內容;
  • getCode():以數字形式返回異常程式碼;
  • getFile():返回發生異常的檔名;
  • getLine():返回發生錯誤的程式碼行號;
  • getTrace():返回 backtrace() 陣列;
  • getTraceAsString():返回已格式化成字串的、由函式 getTrace() 函式所產生的資訊;
  • __toString():產生異常的字串資訊,它可以過載。注意,該函式最前部是兩個下劃線。


下面程式碼是 Exception 類的完整程式碼,從這個類的定義可以看出哪些屬性和方法(成員函式)在使用者派生的子類中是可以訪問和繼承的。

Exception {
    /* 屬性 */
    protected string $message ;
    protected int $code ;
    protected string $file ;
    protected int $line ;
    /* 方法 */
    public __construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]] )
    final public getMessage ( void ) : string
    final public getPrevious ( void ) : Throwable
    final public getCode ( void ) : int
    final public getFile ( void ) : string
    final public getLine ( void ) : int
    final public getTrace ( void ) : array
    final public getTraceAsString ( void ) : string
    public __toString ( void ) : string
    final private __clone ( void ) : void
}

  

捕獲程式中的異常

在 PHP 中想要捕獲程式中的異常,需要使用 try catch 語句和 throw 關鍵字來實現。try catch 語句和流程控制語句類似,所以可以通過 try catch 語句來實現一種另類的條件選擇結構,而 throw 關鍵字則可以丟擲一個異常。try catch 語句的語法格式如下:

try{
    // 可能出現異常或錯誤的程式碼,比如檔案操作、資料庫操作等
}catch(Exception $e){    // $e 為一個異常類的物件
    // 輸出錯誤資訊
}

  需要進行異常處理的程式碼都必須放入 try 程式碼塊內,以便捕獲可能存在的異常。每一個 try 至少要有一個與之對應的 catch。使用多個 catch 可以捕獲不同的類所產生的異常。

當 try 程式碼塊不再丟擲異常或者找不到 catch 能匹配所丟擲的異常時,PHP 程式碼就會在跳轉到最後一個 catch 的後面繼續執行。

在 PHP 程式碼中所產生的異常可以被 throw 語句丟擲並被 catch 語句捕獲。當然,PHP 允許在 catch 程式碼塊內再次丟擲(throw)異常。

當一個異常被丟擲時,其後的程式碼不會再繼續執行,而 PHP 就會嘗試繼續查詢第一個能與之匹配的 catch。如果一個異常沒有被捕獲,而且又沒用使用 set_exception_handler() 作相應的處理的話,將會產生一個嚴重的錯誤,並且輸出 UncaughtException...(未捕獲異常)的提示資訊。

【示例】使用 try catch 和 throw 捕獲程式中的異常。

try{
        $err = '丟擲異常資訊,並跳出 try 語句塊';
        if(is_dir('./test')){
            echo '這裡是一些可能會發生異常的程式碼';
        }else{
            throw new Exception($err, 12345);   // 丟擲異常
        }
        echo '上面丟擲異常的話,這行程式碼將不會執行,轉而執行 catch 中的程式碼。<br>';
    }catch(Exception $e){
        echo '捕獲異常:'.$e->getMessage().'<br>錯誤程式碼:'.$e->getCode().'<br>';
    }
    echo '繼續執行 try catch 語句之外的程式碼';

  執行結果如下:

捕獲異常:丟擲異常資訊,並跳出 try 語句塊
錯誤程式碼:12345
繼續執行 try catch 語句之外的程式碼

  

示例程式碼中,在 try 語句塊中試著判斷當前目錄下是否存在名為 test 的目錄,如果不存在這個目錄,那麼就會執行第 7 行的程式碼,通過關鍵字 throw 丟擲異常。這個異常是一個 Exception 類的物件,通過 new 關鍵字生成,並且用錯誤資訊 $err 和錯誤程式碼 12345 初始化該物件,以便後面 catch 該異常時(程式碼第 11 行),可以獲取這些資訊。

一旦丟擲異常,那麼 try 語句塊中剩下的程式碼就不再繼續執行,程式流程轉至相應的 catch 語句塊執行,最終通過 Exception 物件呼叫其成員函式輸出錯誤資訊和程式碼。

PHP 建立自己的異常類

在各種語言裡,對異常和錯誤的定義不同。在 PHP 裡遇到任何錯誤都會丟擲一個錯誤,很少會主動丟擲異常,不像 Java 語言那樣會預先定義好各種異常類,當程式執行到異常處的程式碼時會主動丟擲。

PHP 的異常處理機制並不完善,在 PHP 中想處理不可預料的異常是辦不到的,必須事先定義一些異常,將各種可能出現的異常進行 if…else 判斷,手動丟擲異常,所以在 PHP 裡經常會使用到我們自己建立的異常類。

下面定義兩個異常類,都繼承自 Exception 基類。

class emailException extends Exception{
    function __toString(){
        return "<b>email is null</b>file:".$this->getFile().',line:'. $this->getLine();
    }
}
class nameException extends Exception{
}

  在實際業務中可根據不同需求丟擲不同異常,業務程式碼如下:

1 function reg($reg) {
2     if (empty($reg['email'])) {
3         throw new emailException("emaill is null", 1);
4     }
5     if(empty($reg['name'])) {
6         throw new nameException("name is null", 2);
7      }
8 }

在執行業務程式碼時,需要使用 if 語句判斷異常會發生的地方,然後手動丟擲異常,將不同的異常分發給不同的異常類處理,如下所示:

 1 try{
 2     $reg = array('phone'=>'1888888888');
 3     reg($reg);
 4 } catch(emailException $e) {
 5     echo $e;
 6 } catch(nameException $e) {
 7     echo 'error msg:' .$e->getMessage().'error code:'.$e->getCode();
 8 } finally {
 9     echo ' finally';
10 }

這段程式根據不同的情況捕獲不同的異常,如果第一個 catch 捕獲了異常,即使程式中仍然存在其他異常,也會跳過其他的 catch 程式碼塊,但是不管程式中是否出現異常,最終 finally 中的語句都會執行。

執行以上程式的結果為:

email is nullfile:/Library/WebServer/Documents/book/try.php,line:39 finally