PHP錯誤和異常詳解(PHP7錯誤處理)

世界上沒有絕對完美的事,對於程序員來講更是如此,不管咱們多麼努力、多麼細心的開發一個項目,總會有缺陷和錯誤的存在。php

錯誤和異常的異同html

"錯誤"和"異常"的概念十分類似,很容易混淆,"錯誤"和"異常"都代表了項目出了問題,都會提供相關的信息,而且都有錯誤類型。然而,"異常機制"是在"錯誤機制"後纔出現的,"異常"是避免"錯誤"的不足。比較重要的一點就是由於"錯誤"的信息不豐富,咱們見過最多的函數說明就是: 成功時候返回***, 錯誤的時候返回FALSE, 然而一個函數出錯的緣由可能有多種, 出錯的種類更有多種. 一個簡單的FALSE, 並不能把具體的錯誤信息告訴調用者.mysql

PHP中將代碼自身異常(通常是環境或者語法非法所致)成爲錯誤,將運行中出現的邏輯錯誤稱爲異常(Exception)錯誤是無法經過代碼處理的,而異常則能夠經過try/catch處理.程序員

異常sql

異常是Exception類的對象,在遇到沒法修復的情況時拋出,出現問題時,異經常使用於主動出擊,委託職責,異常還可用於防守,預測潛在的問題,減輕其影響。app

Exception對象有兩個主要的屬性:一個是消息,另外一個是數字代碼。咱們分別能夠用getCode()和getMessage()獲取這兩個屬性。以下:函數

[php] view plain copyoop

  1. <?php   
  2. $exception = new Exception("figthing!!!",100);  
  3. $code = $exception->getCode();//100  
  4. $message = $exception->getMessage();//fight.....  

拋出異常this

當一個異常被拋出後代碼會當即中止執行,其後的代碼將不會繼續執行,PHP 會嘗試查找匹配的 "catch" 代碼塊。若是一個異常沒有被捕獲,並且又沒用使用set_exception_handler()做相應的處理的話,那麼 PHP 將會產生一個嚴重的錯誤,而且輸出未能捕獲異常(Uncaught Exception ...)的提示信息。spa

[html] view plain copy

  1. throw new Exception("this is a exception");//使用throw拋出異常  

捕獲異常

咱們應該捕獲拋出的異常而且使用優雅的方式處理。攔截並處理異常的方式是,把可能拋出異常的代碼放到try/catch塊中。而且若是使用多個catch攔截多個異常的時候,只會運行其中一個,若是PHP沒有找到合適的catch塊,異常會向上冒泡,直到PHP腳本因爲致命錯誤而終止運行。以下:

[php] view plain copy

  1. try {  
  2.     throw new Exception("Error Processing Request");  
  3.     $pdo = new PDO("mysql://host=wrong_host;dbname=wrong_name");  
  4. } catch (PDOException $e) {  
  5.     echo "pdo error!";  
  6. } catch(Exception $e){  
  7.     echo "exception!";  
  8. }finally{  
  9.     echo "end!";//finally是在捕獲到任何類型的異常後都會運行的一段代碼  
  10. }  

[html] view plain copy

  1. 運行結果:exception!end!  

異常處理程序

那麼咱們應該如何捕獲每一個可能拋出的異常呢?PHP容許咱們註冊一個全局異常處理程序,捕獲全部未被捕獲的異常。異常處理程序使用set_exception_handler()函數註冊(這裏使用匿名函數)。

[php] view plain copy

  1. set_exception_handler(function (Exception $e)  
  2. {  
  3.     echo "我本身定義的異常處理".$e->getMessage();  
  4. });  
  5. throw new Exception("this is a exception");  
  6.   
  7. //運行結果:我本身定義的異常處理this is a exception  

錯誤

除了異常以外,PHP還提供了用於報告錯誤的函數。PHP能觸發不一樣類型的錯誤,例如致命錯誤、運行時錯誤、編譯時錯誤、啓動錯誤以及用戶觸發的錯誤。能夠在php.ini中設置錯誤報告方式(這裏不作多的解釋)

下面列舉一些錯誤報告級別:

值          常量                     說明
1           E_ERROR             報告致使腳本終止運行的致命錯誤
2           E_WARNING           報告運行時的警告類錯誤(腳本不會終止運行)
4           E_PARSE             報告編譯時的語法解析錯誤
8           E_NOTICE            報告通知類錯誤,腳本可能會產生錯誤
32767       E_ALL               報告全部的可能出現的錯誤(不一樣的PHP版本,常量E_ALL的值也可能不一樣)

不管如何都必須遵照如下幾條規則:

  • 必定要讓PHP報告錯誤
  • 在開發環境中要顯示錯誤
  • 在生產環境中不能顯示錯誤
  • 在開發環境和生產環境中都要記錄錯誤

錯誤處理程序

與異常處理程序同樣,咱們也可使用set_error_handler()註冊全局錯誤處理程序,使用本身的邏輯方式攔截並處理PHP錯誤。咱們要在錯誤處理程序中調用die()或exit()函數。若是不調用,PHP腳本會從出錯的地方繼續向下執行。以下:

[php] view plain copy

  1. set_error_handler(function ($errno,$errstr,$errfile,$errline)//經常使用的四個參數  
  2. {  
  3.     echo "錯誤等級:".$errno."<br>錯誤信息:".$errstr."<br>錯誤的文件名:".$errfile."<br>錯誤的行號:".$errline;  
  4.     exit();  
  5. });  
  6.   
  7. trigger_error("this is a error");//自行觸發的錯誤  
  8.   
  9. echo '正常';   

運行結果:
錯誤等級:1024
錯誤信息:this is a error
錯誤的文件名:/Users/toby/Desktop/www/Exception.php
錯誤的行號:33

相關的還有一個函數register_shutdown_function()---是一個會在php停止時執行的函數。(有興趣的能夠自行查詢一下)

錯誤轉換爲異常

咱們能夠把PHP錯誤轉換爲異常(並非全部的錯誤均可以轉換,只能轉換php.ini文件中error_reporting指令設置的錯誤),使用處理異常的現有流程處理錯誤。這裏咱們使用set_error_handler()函數將錯誤信息託管至ErrorException(它是Exception的子類),進而交給現有的異常處系統處理。以下:

[php] view plain copy

  1. set_exception_handler(function (Exception $e)  
  2. {  
  3.     echo "我本身定義的異常處理".$e->getMessage();  
  4. });  
  5.   
  6. set_error_handler(function ($errno, $errstr, $errfile, $errline )  
  7. {  
  8.     throw new ErrorException($errstr, 0, $errno, $errfile, $errline);//轉換爲異常  
  9. });  
  10.   
  11. trigger_error("this is a error");//自行觸發錯誤  

運行結果:我本身定義的異常處理this is a error

PHP7的錯誤異常處理

PHP 7 改變了大多數錯誤的報告方式。不一樣於傳統(PHP 5)的錯誤報告機制,如今大多數錯誤被做爲 Error 異常拋出。

這種 Error 異常能夠像 Exception 異常同樣被第一個匹配的 try / catch 塊所捕獲。若是沒有匹配的 catch 塊,則調用異常處理函數(事先經過 set_exception_handler() 註冊)進行處理。 若是還沒有註冊異常處理函數,則按照傳統方式處理:被報告爲一個致命錯誤(Fatal Error)。

Error 類並不是繼承自 Exception 類,因此不能用 catch (Exception $e) { ... } 來捕獲 Error。你能夠用 catch (Error $e) { ... },或者經過註冊異常處理函數( set_exception_handler())來捕獲 Error。

[php] view plain copy

  1. $a=1;  
  2. try {  
  3. $a->abc();//未定義此對象  
  4. } catch (Exception $e) {  
  5.     echo "error";  
  6. } catch (Error $e) {  
  7.     echo $e->getCode();  
  8. }  

運行結果:0

PHP7 中出現了 Throwable 接口,該接口由 Error 和 Exception 實現,用戶不能直接實現 Throwable 接口,而只能經過繼承 Exception 來實現接口

[php] view plain copy

  1. try {  
  2. // Code that may throw an Exception or Error.  
  3. } catch (Throwable $t) {  
  4. // Executed only in PHP 7, will not match in PHP 5.x  
  5. } catch (Exception $e) {  
  6. // Executed only in PHP 5.x, will not be reached in PHP 7  
  7. }  

注意實際項目中,在開發環境中咱們可使用Whoops組件,在生產環境中咱們可使用Monolog組件。

相關文章
相關標籤/搜索