世界上沒有絕對完美的事,對於程序員來講更是如此,不管咱們多麼努力、多麼細心的開發一個項目,總會有缺陷和錯誤的存在。php
錯誤和異常的異同html
"錯誤"和"異常"的概念十分類似,很容易混淆,"錯誤"和"異常"都代表了項目出了問題,都會提供相關的信息,而且都有錯誤類型。然而,"異常機制"是在"錯誤機制"後纔出現的,"異常"是避免"錯誤"的不足。比較重要的一點就是由於"錯誤"的信息不豐富,咱們見過最多的函數說明就是: 成功時候返回***, 錯誤的時候返回FALSE, 然而一個函數出錯的緣由可能有多種, 出錯的種類更有多種. 一個簡單的FALSE, 並不能把具體的錯誤信息告訴調用者.mysql
PHP中將代碼自身異常(通常是環境或者語法非法所致)成爲錯誤,將運行中出現的邏輯錯誤稱爲異常(Exception)錯誤是無法經過代碼處理的,而異常則能夠經過try/catch處理.程序員
異常sql
異常是Exception類的對象,在遇到沒法修復的情況時拋出,出現問題時,異經常使用於主動出擊,委託職責,異常還可用於防守,預測潛在的問題,減輕其影響。app
Exception對象有兩個主要的屬性:一個是消息,另外一個是數字代碼。咱們分別能夠用getCode()和getMessage()獲取這兩個屬性。以下:函數
[php] view plain copyoop
拋出異常this
當一個異常被拋出後代碼會當即中止執行,其後的代碼將不會繼續執行,PHP 會嘗試查找匹配的 "catch" 代碼塊。若是一個異常沒有被捕獲,並且又沒用使用set_exception_handler()做相應的處理的話,那麼 PHP 將會產生一個嚴重的錯誤,而且輸出未能捕獲異常(Uncaught Exception ...)的提示信息。spa
[html] view plain copy
捕獲異常
咱們應該捕獲拋出的異常而且使用優雅的方式處理。攔截並處理異常的方式是,把可能拋出異常的代碼放到try/catch塊中。而且若是使用多個catch攔截多個異常的時候,只會運行其中一個,若是PHP沒有找到合適的catch塊,異常會向上冒泡,直到PHP腳本因爲致命錯誤而終止運行。以下:
[php] view plain copy
[html] view plain copy
異常處理程序
那麼咱們應該如何捕獲每一個可能拋出的異常呢?PHP容許咱們註冊一個全局異常處理程序,捕獲全部未被捕獲的異常。異常處理程序使用set_exception_handler()函數註冊(這裏使用匿名函數)。
[php] view plain copy
錯誤
除了異常以外,PHP還提供了用於報告錯誤的函數。PHP能觸發不一樣類型的錯誤,例如致命錯誤、運行時錯誤、編譯時錯誤、啓動錯誤以及用戶觸發的錯誤。能夠在php.ini中設置錯誤報告方式(這裏不作多的解釋)
下面列舉一些錯誤報告級別:
值 常量 說明 1 E_ERROR 報告致使腳本終止運行的致命錯誤 2 E_WARNING 報告運行時的警告類錯誤(腳本不會終止運行) 4 E_PARSE 報告編譯時的語法解析錯誤 8 E_NOTICE 報告通知類錯誤,腳本可能會產生錯誤 32767 E_ALL 報告全部的可能出現的錯誤(不一樣的PHP版本,常量E_ALL的值也可能不一樣)
不管如何都必須遵照如下幾條規則:
錯誤處理程序
與異常處理程序同樣,咱們也可使用set_error_handler()註冊全局錯誤處理程序,使用本身的邏輯方式攔截並處理PHP錯誤。咱們要在錯誤處理程序中調用die()或exit()函數。若是不調用,PHP腳本會從出錯的地方繼續向下執行。以下:
[php] view plain copy
運行結果:
錯誤等級: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
運行結果:我本身定義的異常處理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
運行結果:0
PHP7 中出現了 Throwable
接口,該接口由 Error
和 Exception
實現,用戶不能直接實現 Throwable
接口,而只能經過繼承 Exception
來實現接口
[php] view plain copy
注意實際項目中,在開發環境中咱們可使用Whoops組件,在生產環境中咱們可使用Monolog組件。