錯誤,能夠理解程序自己的錯誤,例如語法錯誤。而異常則更偏向於程序運行不符合預期或者不符合正常流程;對於 PHP 語言而言,處理錯誤和處理異常使用的機制徹底不一樣,所以很容易讓人產生困惑。php
例如,咱們但願經過捕獲異常來處理除數爲 0 的狀況,可是在捕獲到異常以前,PHP 就觸發了錯誤。laravel
1 try { 2 $a = 5 / 0; 3 } catch (Exception $e) { 4 $e->getMessage(); 5 $a = -1; // 經過異常來處理 $a 爲 0 的狀況,可是實際上,捕獲不到該異常 6 } 7 8 echo $a; 9 // PHP Warning: Division by zero
也就是說,PHP 將除數爲 0 的狀況當成了錯誤而觸發,而不會自動拋出異常,所以無法捕獲。相似的,在不少狀況下,PHP 都沒辦法自動拋出異常。只能經過 if - else
語句判斷再結合 throw
方法來並手動拋出異常。sql
上述狀況的發生,主要仍是由於異常機制是 PHP 向面向對象演進後獲得的產物。而在此以前 PHP 的報錯主要仍是經過錯誤機制,所以,在不少狀況下,PHP 的錯誤要比異常更有價值。不過 PHP7 開始統一這二者,使錯誤也能夠像異常那樣拋出(這部份內容將放在異常部分講解)。shell
PHP 中的錯誤可理解爲 使腳本不運行不正常的狀況,根據錯誤級別從高到低可劃分爲五類服務器
默認狀況下,PHP 觸發錯誤,並顯示錯誤的級別及對應的提示。架構
Parse Error 示例 - 語句結尾不寫分號併發
1 echo "abc" 2 // PHP Parse error: syntax error, unexpected end of file, expecting ',' or ';
Fatal Error 示例 - 使用不存在的函數分佈式
1 echo "before\n"; 2 foo(); 3 echo "after"; // 本行沒法繼續執行 4 // before 5 // PHP Fatal error: Uncaught Error: Call to undefined function foo()
Warning Error 示例 - 引入不存在的文件函數
1 $a = "foo"; 2 include('bar.php'); 3 echo $a; // 程序繼續執行 4 // PHP Warning: include(bar.php): failed to open stream: No such file or directory ... 5 // foo 6 Notice Error 示例 - 輸出不存在的變量 7 8 echo $foo; 9 echo 12345; 10 // PHP Notice: Undefined variable: foo 11 // 12345
Deprecated Error 示例 - 在一些字符串函數中傳入數字而非字符串微服務
1 strpos('12345', 3); 2 // PHP Deprecated: strpos(): Non-string needles will be interpreted as strings in the future
除了默認觸發消息外,用戶也能夠使用 set_error_handler
函數自定義錯誤處理,大多數錯誤類型均可以進行自定義處理,除了 E_ERROR
、 E_PARSE
、 E_CORE_ERROR
、 E_CORE_WARNING
、 E_COMPILE_ERROR
、 E_COMPILE_WARNING
外。
1 set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] ) : mixed
示例
1 <?php 2 // E_ALL - 處理所有錯誤類型 3 set_error_handler('customError', E_ALL); 4 5 /** 6 * @param int $errno 錯誤的級別 7 * @param string $errstr 錯誤的信息 8 * @param string $errfile 錯誤的文件名(可選) 9 * @param string $errline 錯誤發生的行號(可選) 10 */ 11 function customError(int $errno, string $errstr, string $errfile, string $errline) 12 { 13 echo sprintf('錯誤消息爲 %s', $errstr); 14 } 15 16 $a = 5 / 0; // 錯誤消息爲 Division by zero
用戶也能夠經過 trigger_error
函數來手動觸發一個用戶級別的錯誤(E_USER_ERROR
、E_USER_WARNING
、E_USER_NOTICE
、E_USER_DEPRECATED
)。
1 function division($a, $b) { 2 if($b == 0){ 3 @trigger_error("0 不能做爲除數", E_USER_NOTICE); 4 return -1; 5 } 6 return $a / $b; 7 } 8 9 echo division(10, 0);
一些錯誤處理相關的經常使用配置
error_reporting
- 設置錯誤的報告級別display_errors
- 是否顯示錯誤display_startup_error
- 是否顯示 PHP 啓動過程當中的顯示log_errors
- 設置是否將腳本運行的錯誤信息記錄到服務器錯誤日誌或者 error_log 之中《Modern PHP》提出了四個規則
開發環境推薦配置
1 display_errors = On 2 display_startup_error = On 3 error_reporting = -1 4 log_errors = On
生產環境推薦配置
1 display_errors = Off 2 display_startup_error = Off 3 ; 報告 Notice 之外的全部錯誤 4 error_reporting = E_ALL & ~E_NOTICE 5 log_errors = On 6
異常和錯誤消息字符串必須使用 sprintf
來進行拼接;
throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
當錯誤類型爲 E_USER_DEPRECATED
時,須要添加 @
@trigger_error("foo", E_USER_DEPRECATED);
參考資料