世界上沒有絕對完美的事,對於程式設計師來說更是如此,無論我們多麼努力、多麼細心的開發乙個專案,總會有缺陷和錯誤的存在。
錯誤和異常的異同
"錯誤"和"異常"的概念十分相似,很容易混淆,"錯誤"和"異常"都表明了專案出了問題,都會提供相關的資訊,並且都有錯誤型別。然而,"異常機制"是在"錯誤機制"後才出現的,"異常"是避免"錯誤"的不足。比較重要的一點就是因為"錯誤"的資訊不豐富,我們見過最多的函式說明就是: 成功時候返回***, 錯誤的時候返回false, 然而乙個函式出錯的原因可能有多種, 出錯的種類更有多種. 乙個簡單的false, 並不能把具體的錯誤資訊告訴呼叫者.
php中將**自身異常(一般是環境或者語法非法所致)成為錯誤,將執行**現的邏輯錯誤稱為異常(exception)錯誤是沒法通過**處理的,而異常則可以通過try/catch處理.
異常異常是exception類的物件,在遇到無法修復的狀況時丟擲,出現問題時,異常用於主動出擊,委託職責,異常還可用於防守,**潛在的問題,減輕其影響。
exception物件有兩個主要的屬性:乙個是訊息,另乙個是數字**。我們分別可以用getcode()和getmessage()獲取這兩個屬性。如下:
<?php
$exception = new exception("figthing!!!",100);
$code = $exception->getcode();//100
$message = $exception->getmessage();//fight.....
丟擲異常
當乙個異常被丟擲後**會立即停止執行,其後的**將不會繼續執行,php 會嘗試查詢匹配的 "catch" **塊。如果乙個異常沒有**獲,而且又沒用使用set_exception_handler()作相應的處理的話,那麼 php 將會產生乙個嚴重的錯誤,並且輸出未能捕獲異常(uncaught exception ...)的提示資訊。
throw new exception("this is a exception");//使用throw丟擲異常
捕獲異常
我們應該捕獲丟擲的異常並且使用優雅的方式處理。攔截並處理異常的方式是,把可能丟擲異常的**放到try/catch塊中。並且如果使用多個catch攔截多個異常的時候,只會執行其中乙個,如果php沒有找到合適的catch塊,異常會向上冒泡,直到php指令碼由於致命錯誤而終止執行。如下:
try catch (pdoexception $e) catch(exception $e)finally
執行結果:exception!end!
異常處理程式
那麼我們應該如何捕獲每個可能丟擲的異常呢?php允許我們註冊乙個全域性異常處理程式,捕獲所有未**獲的異常。異常處理程式使用set_exception_handler()函式註冊(這裡使用匿名函式)。
set_exception_handler(function (exception $e)
);throw new exception("this is a exception");
//執行結果:我自己定義的異常處理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指令碼會從出錯的地方繼續向下執行。如下:
set_error_handler(function ($errno,$errstr,$errfile,$errline)//常用的四個引數
);trigger_error("this is a error");//自行觸發的錯誤
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的子類),進而交給現有的異常處系統處理。如下:
set_exception_handler(function (exception $e)
);set_error_handler(function ($errno, $errstr, $errfile, $errline )
);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。
$a=1;
try catch (exception $e) catch (error $e)
執行結果:0
php7 **現了 throwable 介面,該介面由 error 和 exception 實現,使用者不能直接實現 throwable 介面,而只能通過繼承 exception 來實現介面
try catch (throwable $t) catch (exception $e)
注意實際專案中,在開發環境中我們可以使用whoops元件,在生產環境中我們可以使用monolog元件。
聊聊php7 錯誤與異常處理
1,php7 的錯誤機制都會被丟擲乙個異常,普通錯誤會丟擲乙個 errorexception 異常,致命錯誤會丟擲乙個 error 異常。如果沒有定義錯誤處理,異常處理,則會被 php自身預設錯誤異常處理。如果同時自定義了 set error handler 錯誤處理,與 set exception...
PHP7 異常處理
php 7 異常用於向下相容及增強舊的assert 函式。它能在生產環境中實現零成本的斷言,並且提供拋出自定義異常及錯誤的能力。老版本的api出於相容目的將繼續被維護,assert 現在是乙個語言結構,它允許第乙個引數是乙個表示式,而不僅僅是乙個待計算的 string或乙個待測試的boolean。a...
php7中的異常和錯誤處理
在php7.版本中,一些error和exception可以通過try catch語句捕獲到 可捕獲的異常 錯誤大致有以下三種 error php核心丟擲錯誤的專用型別,如類不存在,函式不存在,函式引數錯誤,都會丟擲此型別的錯誤,php 中不應該使用error類來作為異常丟擲 exception 應用...