首先聲明,筆者 php版本 7.2
異常是指程序運行中不符合預期狀況以及與正常流程不一樣的情況。php
好比你連接數據庫,在參數都寫上去的條件下,發現連接不上去,這就屬於不符合預期 html
能夠被 try-catch 捕捉獲得thinkphp
是屬於php程序自身的問題,通常是由非法的語法,環境問題致使的,使得編譯器沒法經過檢查,甚至沒法運行的狀況。
平時遇到的 warming、notice都是錯誤,只是級別不一樣而已。 數據庫
例如:segmentfault
除了這幾種狀況,其他所有爲異常數組
在之前的 php5.X 中 而且不能被 try-catch 捕捉獲得,到了 php 7.x 中,定義了一個 Throwable 接口 並使得大部分的 Error 和
Exception 實現了該接口,咱們得以在 try-catch 中拋出該錯誤swoole
因此說之後想要捕獲異常,而你又不知道此異常是 Error 仍是 Exception 的話,能夠向這樣拋出app
try{ …… }catch(Throwable $e){ …… }
在 php 中的錯誤也是有級別的框架
Parse error
>Fatal Error
> Waning
> Notice
> Deprecated
函數
Deprecated 最低級別的錯誤(不推薦,不建議) 使用一些過時函數的時候會出現,程序繼續執行 Notice 通知級別的錯誤 使用一些未定義變量、常量或者數組key沒有加引號的時候會出現,程序繼續執行 E_NOTICE // 運行時通知。表示腳本遇到可能會表現爲錯誤的狀況. E_USER_NOTICE // 用戶產生的通知信息。 Waning 警告級別的錯誤 程序出問題了,須要修改代碼!!!程序繼續執行 E_WARNING // 運行時警告 (非致命錯誤)。 E_CORE_WARNING // PHP初始化啓動過程當中發生的警告 (非致命錯誤) 。 E_COMPILE_WARNING // 編譯警告 E_USER_WARNING // 用戶產生的警告信息 Fatal Error 錯誤級別的錯誤 程序直接報錯,須要修改代碼!!!中斷程序執行,可以使用register_shutdown_function()函數在程序終止前觸發一個函數 E_ERROR // 致命的運行錯誤,錯誤沒法恢復,暫停執行腳本 E_CORE_ERROR // PHP啓動時初始化過程當中的致命錯誤 E_COMPILE_ERROR // 編譯時致命性錯,就像由Zend腳本引擎生成了一個E_ERROR E_USER_ERROR // 自定義錯誤消息。像用PHP函數trigger_error(錯誤類型設置爲:E_USER_ERROR) Parse error 語法解析錯誤 語法檢查階段報錯,須要修改代碼!!!中斷程序執行,除了修改ini文件,將錯誤信息寫到日誌中,什麼也作不了 E_PARSE //編譯時的語法解析錯誤
有的時候,php 中自帶的錯誤處理程序,並不能徹底知足咱們得須要,大部分時候,咱們都須要手動重寫異常處理。
php 給咱們提供了三個函數來幫助咱們來處理,分別是
set_error_handler()
set_exception_handler()
register_shutdown_function()
error_get_last()
它能獲取最後發生的錯誤。// 舉例: register_shutdown_function('shutdown'); function shutdown() { if ($error = error_get_last()) { var_dump($error); } } $name //沒寫 ; 號
執行結果 Parse error: syntax error, unexpected ';' in /app/swoole/errorDemo.php on line 34
Emmmmm 這不扯淡嗎? 分明分明沒有執行呢?
其實緣由使由於,程序執行前,咱們 php 會先檢查咱們程序的語法問題,若是沒有問題,咱們才能執行咱們的程序。
咱們上面的代碼沒用經過咱們的語法檢查,因此直接報錯。
那麼問題來了? 咱們在框架中的時候,爲何是框架都是框架給咱們報錯呢?
在框架中,其代碼是經過一個入口文件來加載的。而咱們php檢測語法錯誤的時候,只檢查咱們的 index.php 有沒有錯誤, require 文件中的代碼是不會受到檢測的。在Index.php
文件中一般會定義一些錯誤異常的處理。當咱們代碼出錯時,那是在 run-time 中檢測的錯誤,咱們的框架能夠根據咱們編寫的錯誤異常自行作出處理。
下面咱們舉個例子 在 ThinkPHP5.2 中的異常處理
// [ 應用入口文件 ] index.php namespace think; // 加載基礎文件 require __DIR__ . '/../thinkphp/base.php'; // 支持事先使用靜態方法設置Request對象和Config對象 // 執行應用並響應 Container::get('app')->run()->send();
在咱們的入口文件中,加載了 base.php
在這個文件中,TP 定義了本身的異常處理
// 載入Loader類 require __DIR__ . '/library/think/Loader.php'; // 註冊自動加載 Loader::register(); // 註冊錯誤和異常處理機制 Error::register(); // 實現日誌接口 if (interface_exists('Psr\Log\LoggerInterface')) { //doSomething } // 註冊類庫別名 Loader::addClassAlias([ //doSomething ]);
/** * 註冊異常處理 * @access public * @return void */ public static function register() { error_reporting(E_ALL); set_error_handler([__CLASS__, 'appError']); set_exception_handler([__CLASS__, 'appException']); register_shutdown_function([__CLASS__, 'appShutdown']); }
能夠看到 TP是在入口腳本就註冊了 異常處理機制,分別把 Error 、Exception、Shutdown的處理都註冊進來。後序全部的異常都不會走PHP本來的異常而是走 TP 自定義的異常
本文參考資料