PHP - 錯誤處理



PHP 中的錯誤處理是指在 PHP 程式碼中設定機制,以有效地識別和恢復程式可能遇到的執行時錯誤。在 PHP 中,錯誤處理藉助於:

  • die() 函式

  • 錯誤處理函式

die() 函式

die() 函式是 PHP 中 exit() 的別名。兩者都會在遇到時終止當前 PHP 指令碼的執行。如果在括號中指定一個可選字串,則該字串將在程式終止之前輸出。

die("message");

示例

以下程式碼是 PHP 指令碼中 die() 的典型用法。如果 PHP 找不到檔案,它會顯示“檔案未找到”訊息,否則繼續開啟檔案以進行後續處理。

<?php
   if(!file_exists("nosuchfile.txt")) {
      die("File not found");
   } else {
      $file = fopen("nosuchfile","r");
      print "Opend file sucessfully";
	  
      // Rest of the code here.
      fclose($file);
   }
?>

它將產生以下輸出

File not found

使用上述技術,您可以隨時停止程式錯誤並顯示更有意義且使用者友好的訊息,而不是讓 PHP 生成致命的錯誤訊息。

錯誤處理函式

使用 die() 進行錯誤處理被認為是一種笨拙且設計不良的程式,因為它會導致網站使用者體驗不佳。PHP 提供了一個更優雅的替代方案,您可以使用它來定義自定義函式並將其指定為錯誤處理函式。

set_error_handler() 函式具有以下引數:

set_error_handler(?callable $callback, int $error_levels = E_ALL): ?callable

第一個引數是使用者定義的函式,每當遇到錯誤時都會自動呼叫。

自定義錯誤處理回撥函式應具有以下引數:

handler(
   int $errno,
   string $errstr,
   string $errfile = ?,
   int $errline = ?,
   array $errcontext = ?
): bool

引數

引數 重要性 描述
errno 必需 它指定使用者定義錯誤的錯誤級別。它必須是數值。
errstr 必需 它指定使用者定義錯誤的錯誤訊息。
errfile 可選 它指定發生錯誤的檔名。
errline 可選 它指定發生錯誤的行號。
errcontext 可選 它指定一個數組,其中包含發生錯誤時正在使用的變數及其值。

如果回撥函式返回 false,則將呼叫預設錯誤處理程式。

$errno 是與預定義錯誤級別相對應的整數。

序號 常量和描述
1

E_ERROR (int)

無法恢復的致命執行時錯誤。指令碼執行將停止。

1
2

E_WARNING (int)

執行時警告(非致命錯誤)。指令碼執行不會停止。

2
3

E_PARSE (int)

編譯時解析錯誤。解析錯誤應該只由解析器生成。

4
4

E_NOTICE (int)

執行時通知。可能表示錯誤,但也可能在指令碼正常執行過程中發生。

8
5

E_CORE_ERROR (int)

在 PHP 初始啟動期間發生的致命錯誤。這類似於E_ERROR

16
6

E_CORE_WARNING (int)

在 PHP 初始啟動期間發生的警告(非致命錯誤)。這類似於E_WARNING

32
7

E_COMPILE_ERROR (int)

致命的編譯時錯誤。這類似於E_ERROR

64
8

E_COMPILE_WARNING (int)

編譯時警告(非致命錯誤)。這類似於E_WARNING

128
9

E_USER_ERROR (int)

使用者生成的錯誤訊息。這類似於E_ERROR,由使用 PHP 函式 trigger_error() 生成的 PHP 程式碼生成。

256
10

E_USER_WARNING (int)

使用者生成的警告訊息。這類似於E_WARNING,由使用 trigger_error() 函式生成的 PHP 程式碼生成。

512
11

E_USER_NOTICE (int)

使用者生成的通知訊息。這類似於由使用 trigger_error() 函式生成的 PHP 程式碼生成的E_NOTICE

1024
12

E_STRICT (int)

啟用此選項後,PHP 將建議對您的程式碼進行更改,以確保程式碼的最佳互操作性和前向相容性。

2048
13

E_RECOVERABLE_ERROR (int)

可捕獲的致命錯誤。如果使用者定義的處理程式未捕獲該錯誤,則應用程式將像E_ERROR一樣中止。

4096
14

E_DEPRECATED (int)

執行時通知。啟用此選項可接收有關將來版本中無效程式碼的警告。

8192
15

E_USER_DEPRECATED (int)

使用者生成的警告訊息。這類似於由使用 trigger_error() 函式生成的 PHP 程式碼生成的E_DEPRECATED

16384
16

E_ALL (int)

所有錯誤、警告和通知。

32767

示例

請檢視以下示例:

<?php
   error_reporting(E_ERROR);

   function myerrorhandler($errno, $errstr) {
      echo "error No: $errno Error message: $errstr" . PHP_EOL;
      echo "Terminating PHP script"; 
      die();
   }

   set_error_handler("myerrorhandler");

   $f = fopen("nosuchfile.txt", "r");
   echo "file opened successfully";
   // rest of the code
   fclose($f);
?>

它將產生以下輸出

error No: 2 Error message: fopen(nosuchfile.txt): Failed to open stream: No 
such file or directory
Terminating PHP script

PHP 的錯誤類層次結構從 Throwable 介面開始。PHP 中所有預定義的 Error 類都繼承自 Error 類。

ArithmeticError 類

ArithmeticError 類繼承自Error 類。此類錯誤可能在執行某些數學運算時發生,例如按負數進行按位移位運算。

示例

請檢視以下示例:

<?php
   try {
      $a = 10;
      $b = -3;
      $result = $a << $b;
   } 
   catch (ArithmeticError $e) {
      echo $e->getMessage(); 
   }
?>

它將產生以下輸出

Bit shift by negative number

當對 intdiv() 函式的呼叫導致超出整數合法邊界的值時,也會丟擲此錯誤。

示例

請檢視以下示例:

<?php
   try {
      $a = PHP_INT_MIN;
      $b = -1;
      $result = intdiv($a, $b);
      echo $result;
   } 
   catch (ArithmeticError $e) {
      echo $e->getMessage(); 
   } 
?>

它將產生以下輸出

Division of PHP_INT_MIN by -1 is not an integer

DivisionByZeroError

DivisionByZeroError 類是 ArithmeticError 類的子類。當除法運算中的分母值為零時,就會發生此類錯誤。

示例:模零

請看下面的例子

<?php
   try {
      $a = 10;
      $b = 0;
      $result = $a%$b;
      echo $result;
   } 
   catch (DivisionByZeroError $e) {
      echo $e->getMessage(); 
   }
?>

它將產生以下輸出

Modulo by zero

當模運算子 (%) 的第二個運算數為 0,以及 intdiv() 函式的第二個引數為 0 時,也會發生這種情況。

示例:除以零

請檢視以下示例:

<?php
   try {
      $a = 10;
      $b = 0;
      $result = $a/$b;
      echo $result;
   } 
   catch (DivisionByZeroError $e) {
      echo $e->getMessage(); 
   }
?>

它將產生以下輸出

Division by zero 

ArgumentCountError

當傳遞給使用者自定義函式或方法的引數少於其定義中的引數時,PHP 解析器會丟擲 ArgumentCountError。

示例

請檢視以下示例:

<?php
   function add($x, $y) {
      return $x+$y;
   }
   try {
      echo add(10);
   }
   catch (ArgumentCountError $e) {
      echo $e->getMessage();
   }
?>

它將產生以下輸出

Too few arguments to function add(), 1 passed in C:\xampp\php\test.php on line 9 and exactly 2 expected

TypeError

當實際引數型別和形式引數型別不匹配,或者返回型別與宣告的返回型別不匹配時,就會引發此錯誤。

示例

請檢視以下示例:

<?php
   function add(int $first, int $second) {
      echo "addition: " . $first + second;
   }

   try {
      add('first', 'second');
   } 
   catch (TypeError $e) {
      echo $e->getMessage(), "";
   }
?>

它將產生以下輸出

add(): Argument #1 ($first) must be of type int, string given, 
   called in /home/cg/root/63814/main.php on line 7

當傳遞給 PHP 內建函式的引數數量不正確時,也會丟擲 TypeError。但是,必須在開頭設定 "strict_types=1" 指令。

示例

請檢視以下示例:

<?php
   declare(strict_types=1);
   try {
      echo pow(100,2,3);
   }
   catch (TypeError $e) {
      echo $e->getMessage(), "";
   }
?>

它將產生以下輸出

pow() expects exactly 2 parameters, 3 given

PHP 中的異常處理

PHP 具有與其他程式語言類似的異常模型。異常非常重要,它提供了更好的錯誤處理控制。

讓我們解釋一下與異常相關的新的關鍵字。

  • Try − 使用異常的函式應該放在 "try" 塊中。如果異常沒有觸發,程式碼將正常繼續執行。但是,如果異常觸發,則會“丟擲”異常。

  • Throw − 這是觸發異常的方式。“throw” 必須至少有一個“catch”。

  • Catch − "catch" 塊檢索異常並建立一個包含異常資訊的 物件。

當丟擲異常時,該語句後面的程式碼將不會執行,PHP 將嘗試查詢第一個匹配的 catch 塊。如果沒有捕獲異常,則會發出 PHP 致命錯誤,提示“未捕獲的異常…”

  • 可以在 PHP 中丟擲異常並捕獲(“catch”)異常。程式碼可以用 try 塊包圍。

  • 每個 try 必須至少有一個對應的 catch 塊。可以使用多個 catch 塊來捕獲不同類別的異常。

  • 可以在 catch 塊中丟擲(或重新丟擲)異常。

示例

下面是一段程式碼,請複製並貼上這段程式碼到一個檔案中並驗證結果。

<?php
   try {
      $error = 'Always throw this error';
      throw new Exception($error);
      
      // Code following an exception is not executed.
      echo 'Never executed';
   }catch (Exception $e) {
      echo 'Caught exception: ',  $e->getMessage(), "";
   }
   
   // Continue execution
   echo 'Hello World';
?>

在上面的例子中,使用 $e->getMessage 函式獲取錯誤資訊。以下是一些可以從Exception 類中使用的函式。

  • getMessage() − 異常資訊

  • getCode() − 異常程式碼

  • getFile() − 原始檔名

  • getLine() − 原始碼行號

  • getTrace() − backtrace() 的陣列

  • getTraceAsString() − 格式化的跟蹤字串

建立自定義異常處理程式

您可以定義自己的自定義異常處理程式。使用以下函式來設定使用者定義的異常處理程式函式。

string set_exception_handler ( callback $exception_handler )

這裡exception_handler 是發生未捕獲異常時要呼叫的函式的名稱。必須在呼叫 set_exception_handler() 之前定義此函式。

示例

請檢視以下示例:

<?php
   function exception_handler($exception) {
      echo "Uncaught exception: " , $exception->getMessage(), "\n";
   }
	
   set_exception_handler('exception_handler');
   throw new Exception('Uncaught Exception');
   
   echo "Not Executed";
?>

檢視完整的錯誤處理函式集,請訪問 PHP 錯誤處理函式

廣告