最新的Web開發教程
 

PHP異常處理


例外用於如果發生指定的錯誤改變腳本的正常流動。


什麼是異常

隨著PHP 5來處理錯誤的一個新的面向對象的方式。

異常處理用於如果指定的錯誤改變代碼執行的正常流動(exceptional)條件發生。 這種情況被稱為異常。

這是當異常被觸發,通常會發生什麼:

  • 當前代碼狀態被保存
  • 該代碼執行將切換到預定義的(custom)異常處理函數
  • 根據不同的情況,處理程序就可以恢復的代碼保存狀態下執行,中止執行腳本或從其他位置繼續腳本代碼

我們會表現出不同的錯誤處理方法:

  • 基本使用的例外
  • 創建自定義異常處理程序
  • 多個異常
  • 重新拋出異常
  • 設置頂層異常處理程序

Note:例外只應該錯誤的條件下使用,而不應使用在指定點跳轉到另一地點的代碼。


例外的基本使用

當一個異常被拋出,下面的代碼就不會被執行,而PHP將試圖找到匹配的"catch"塊。

如果一個異常沒有被捕獲,一個致命的錯誤將與發出"Uncaught Exception"消息。

讓我們試著拋出一個異常,不會夾住它:

<?php
//create function with an exception
function checkNum($number) {
  if($number>1) {
    throw new Exception("Value must be 1 or below");
  }
  return true;
}

//trigger exception
checkNum(2);
?>

上面的代碼會獲得類似這樣的錯誤:

Fatal error : Uncaught exception 'Exception'
with message 'Value must be 1 or below' in C:\webfolder\test.php:6
Stack trace: #0 C:\webfolder\test.php(12):
checkNum(28) #1 {main} thrown in C:\webfolder\test.php on line 6

嘗試,拋出和捕獲

為了避免從上面例子中的錯誤,我們需要創建適當的代碼來處理異常。

適當的異常代碼應包括:

  1. 使用異常應在一個功能-嘗試"try"塊。 如果異常不會觸發,代碼將繼續正常。 但是,如果觸發的例外,一個異常"thrown"
  2. 扔掉 - 這是你如何觸發一個例外。 每一個"throw"必須至少有一個"catch"
  3. 捉-甲"catch"塊檢索一個例外,並創建包含異常信息的對象

讓我們嘗試觸發有效代碼的異常:

<?php
//create function with an exception
function checkNum($number) {
  if($number>1) {
    throw new Exception("Value must be 1 or below");
  }
  return true;
}

//trigger exception in a "try" block
try {
  checkNum(2);
  //If the exception is thrown, this text will not be shown
  echo 'If you see this, the number is 1 or below';
}

//catch exception
catch(Exception $e) {
  echo 'Message: ' .$e->getMessage();
}
?>

上面的代碼會獲得類似這樣的錯誤:

Message: Value must be 1 or below

為例進行了說明:

上面的代碼拋出異常和捕獲它:

  1. 所述checkNum()創建功能。 它檢查,如果數大於1,如果是,則拋出異常
  2. checkNum()函數被調用一個"try"
  3. 該範圍內的異常checkNum()函數拋出
  4. "catch"塊檢索異常,並創建一個對象($e)包含異常信息
  5. 從異常的錯誤消息是由呼叫呼應$e-> getMessage()從所述異常對象

然而,一個辦法讓周圍的"every throw must have a catch"規則是設定一個最高水平異常處理程序來處理漏網之魚錯誤。


創建一個自定義異常類

要創建您必須創建一個特殊類時異常在PHP時,可以調用函數的自定義異常處理程序。 類必須是異常類的擴展。

自定義異常類從PHP的異常類繼承的屬性,你可以添加自定義的功能吧。

讓我們創建一個異常類:

<?php
class customException extends Exception {
  public function errorMessage() {
    //error message
    $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
    .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
    return $errorMsg;
  }
}

$email = "[email protected]";

try {
  //check if
  if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
    //throw exception if email is not valid
    throw new customException($email);
  }
}

catch (customException $e) {
  //display custom message
  echo $e->errorMessage();
}
?>

新的類是舊的例外類與另外的一個副本errorMessage()函數。 既然是老類的副本,並將其從舊的類繼承的屬性和方法,我們可以使用異常類的方法,如getLine()getFile()getMessage()

為例進行了說明:

上面的代碼拋出異常,並用一個定制的異常類捕獲它:

  1. customException()類為舊的例外類的擴展創建。 這樣,它繼承了舊的例外類的所有方法和屬性
  2. 所述errorMessage()創建功能。 如果電子郵件地址無效,該函數返回一個錯誤信息
  3. 在$電子郵件變量設置為一個字符串,這不是一個有效的電子郵件地址
  4. "try"塊被執行並拋出一個異常,因為電子郵件地址無效
  5. "catch"塊捕捉異常並顯示錯誤消息

多個異常

這是可能的腳本中使用多個異常檢查多個條件。

有可能使用幾種的if..else塊,一個開關,或嵌套多個異常。 這些例外可以使用不同的異常類返回不同的錯誤信息:

<?php
class customException extends Exception {
  public function errorMessage() {
    //error message
    $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
    .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
    return $errorMsg;
  }
}

$email = "[email protected]";

try {
  //check if
  if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
    //throw exception if email is not valid
    throw new customException($email);
  }
  //check for "example" in mail address
  if(strpos($email, "example") !== FALSE) {
    throw new Exception("$email is an example e-mail");
  }
}

catch (customException $e) {
  echo $e->errorMessage();
}

catch(Exception $e) {
  echo $e->getMessage();
}
?>

為例進行了說明:

上面的代碼測試兩個條件,並且如果任一條件不滿足拋出異常:

  1. customException()類為舊的例外類的擴展創建。 這樣,它繼承了舊的例外類的所有方法和屬性
  2. 所述errorMessage()創建功能。 如果電子郵件地址無效,該函數返回一個錯誤信息
  3. 在$電子郵件變量設置為一個字符串,是一個有效的電子郵件地址,但包含字符串"example"
  4. "try"塊被執行,一個異常沒有拋出的第一個條件
  5. 由於電子郵件包含字符串的第二個條件觸發的異常"example"
  6. "catch"塊捕捉異常並顯示正確的錯誤消息

如果拋出的異常是類customException並沒有customException抓,只有基本異常捕獲,異常將在那裡處理。


重新拋出異常

有時,當拋出一個異常,你可能希望以不同的方式處理它比標準的方式。 它可以拋出一個異常內的第二次"catch"塊。

腳本應該對用戶隱藏系統錯誤。 系統錯誤可能是編碼器很重要,但不感興趣的用戶。 為了讓事情變得更容易為用戶,您可以重新引發與用戶友好的消息的異常:

<?php
class customException extends Exception {
  public function errorMessage() {
    //error message
    $errorMsg = $this->getMessage().' is not a valid E-Mail address.';
    return $errorMsg;
  }
}

$email = "[email protected]";

try {
  try {
    //check for "example" in mail address
    if(strpos($email, "example") !== FALSE) {
      //throw exception if email is not valid
      throw new Exception($email);
    }
  }
  catch(Exception $e) {
    //re-throw exception
    throw new customException($email);
  }
}

catch (customException $e) {
  //display custom message
  echo $e->errorMessage();
}
?>

為例進行了說明:

上述測試的代碼,如果電子郵件地址包含字符串"example"在裡面,如果這樣做,異常被重新拋出:

  1. customException()類為舊的例外類的擴展創建。 這樣,它繼承了舊的例外類的所有方法和屬性
  2. 所述errorMessage()創建功能。 如果電子郵件地址無效,該函數返回一個錯誤信息
  3. 在$電子郵件變量設置為一個字符串,是一個有效的電子郵件地址,但包含字符串"example"
  4. "try"塊包含另一個"try"塊,使之可能重新拋出異常
  5. 被觸發的異常,因為電子郵件包含字符串"example"
  6. "catch"塊捕獲該異常,並重新拋出一個"customException"
  7. 所述"customException"被捕獲並顯示錯誤消息

如果該異常不能在其目前陷入"try"塊,它將搜索在catch塊"higher levels"


設置頂層異常處理

所述set_exception_handler()函數將用戶定義的函數來處理所有的未捕獲的異常。

<?php
function myException($exception) {
  echo "<b>Exception:</b> " . $exception->getMessage();
}

set_exception_handler('myException');

throw new Exception('Uncaught Exception occurred');
?>

以上代碼的輸出應該是這樣的:

Exception: Uncaught Exception occurred

在上面的代碼沒有"catch"塊。 取而代之的是,頂層異常處理觸發。 此功能可用於捕捉未捕獲的異常。


規則的例外

  • 代碼可以在try塊包圍,以幫助捕捉到潛在的異常
  • 每個try塊或"throw"必須至少有一個與之對應的catch
  • 多個catch可以用來捕獲不同的類的例外
  • 異常可以被拋出(or re-thrown)在catch塊try塊內

一個簡單的規則:如果你扔東西,你必須抓住它。