系統化理解PHP的錯誤和異常

藏色散人
發布: 2023-04-07 19:18:02
轉載
1838 人瀏覽過

PHP語言簡單的原因之一就是PHP的錯誤處理機制,隨著PHP語言越來越現代化,也出現了異常,這篇博文就是簡單說下錯誤和異常,以便系統的理解,另外對於任何一種語言來說,異常的存在是具備共性的,所以學習一門語言理解異常機制是必不可少的.

#什麼是錯誤

##當PHP語言遇到異常的情況(例如資料庫連線不上或函數參數傳遞錯誤),則會報出一些錯誤,錯誤可以分為多種型別,除了E_ERROR和E_CORE_ERROR錯誤,其它錯誤不會終止程式執行.

PHP讓人覺得簡單的原因就在於程式不會頻繁的報錯,給人一種編寫流暢和方便的錯覺.

也正因為這個原因PHP程式的嚴謹性和準確性差了不少,比如mysql_fetch_array查詢遇到網路錯誤回傳FALSE的時候(程式沒有終止運行),假如調用程式認為查詢沒有匹配的資料,則這個程式本質是錯誤的.

#透過php. ini的指令error_reporting或動態呼叫error_reporting()函數我們可以選擇報告什麼類型的錯誤,透過display_errors指令則可以控制錯誤是否在線輸出.而error_log指令可以控制將錯誤輸出到日誌中.

#如何正確使用錯誤

不管是系統函數或是自訂函數,假如內部遇到錯誤,如何告之呼叫者呢?一般是透過函數傳回TRUE或FALSE來表示.這種處理方式有幾個弊端:

● 呼叫者只知道發生了錯誤,但是回傳的錯誤訊息太少,且缺乏錯誤類型的說明

● 程式處理邏輯和錯誤處理混雜在一塊,產生的程式碼會非常的不清晰.

一個小技巧: error_get_last()函數會傳回最近錯誤產生的具體原因.

最佳實務:

● set_error_handler()函數來託管所有的錯誤

● trigger_error()函數可以觸發自訂錯誤,可以用來在函數中取代return 語句

# ● 將所有的錯誤輸出到日誌中,同時定義錯誤類型

● 對使用者顯示錯誤,例如將錯誤以一種更友善的方式傳回給使用者

● 生產環境下display_errors指令要關閉,開發環境則指令開啟

老牌的PHP框架Codeigniter處理錯誤的方式可以藉用

function _error_handler($severity, $message, $filepath, $line)
{
    $is_error = (((E_ERROR | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity);
    //输出500错误HTTP状态码
    if ($is_error) {
        set_status_header(500);
    }
    //对于不需要处理的错误则直接中断
    if (($severity & error_reporting()) !== $severity) {
        return;
    }
    //将所有的错误记录到日志中
    $_error =& load_class('Exceptions', 'core');
    $_error->log_exception($severity, $message, $filepath, $line);
    //友好的输出所有错误
    if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors'))){
        $_error->show_php_error($severity, $message, $filepath, $line);
    }
    //假如致命错误则直接退出
    if ($is_error) {
        exit(1);   
    }
}
set_error_handler('_error_handler');
登入後複製

什麼是異常

#異常也是一個錯誤,它具備以下的特點:

● 異常可以自訂,SPL提供了很多類型的異常,你也可以擴展它

##● 異常最常規的動作就是捕獲,這樣開發者就能根據具體的錯誤進行後續處理.比如可以根據異常的上下文給用戶返回友好的提示.或者繼續拋出一個異常,讓上游的程序去處理.假如還是沒有捕獲異常,那麼程序就直接終止了.

● 異常另外個動作就是拋出,假如透過函數編寫業務邏輯,遇到意外的情況,可以直接丟出一個異常.

● 異常可以被程式碼一層一層捕獲,假如最外層的程式還沒有捕獲,則代碼直接終止運行

● PHP中的異常假如不能捕獲,則作為致命錯誤寫入到系統錯誤日誌中

透過直覺的程式碼來說明下:

function inverse($x)
{
    if ($x < 10) {
        throw new Exception(&#39;x<10&#39;);
    } elseif ($x >= 10 and $x < 100) {
        throw new LogicException(&#39;x>=10 and x<100&#39;);
    }
    return $x;
}
try {
    echo inverse(2)."\n";
} catch (LogicException $e) {
    echo &#39;Caught LogicException: &#39;, $e->getMessage(), "\n";
} catch (Exception $e) {
    echo &#39;Caught Exception: &#39;, $e->getMessage(), "\n";
    throw $e;
}
登入後複製

異常的最佳實踐

#● 異常可以讓程式碼更加清晰,讓開發者專注於業務邏輯的編寫.

● 建構可擴展的異常是非常有技術性的,難道SPL異常還做的不夠嗎?

● 捕獲異常應該僅僅捕獲本層能處理的異常,對於不能處理的異常則讓上游的程式碼處理.

PHP7中的異常

PHP7鼓勵使用異常來代替錯誤,但是不可能一下子推翻錯誤處理機制,需要相容,所以只能慢慢過渡.

但是可以透過變通的方式來統一使用異常

#● Error異常

PHP中定義了一個Error異常,注意這個異常和Exception是並列的,

當打開嚴格模式的時候,PHP7中很多的錯誤是被Error異常拋出的.這樣就能統一使用異常了.

declare (strict_types = 1);
function add(int $a, int $b)
{
    return $a + $b;
}
try {
    echo add("3", "4");
}
catch (TypeError $e) { //TypeError继承自Error
    echo $e->getMessage();
}
登入後複製

 ErrorException

ErrorException繼承自Exception.

我們可以透過set_error_handler()函數將所有的錯誤轉換成ErrorException.這樣就能愉快的統一使用異常了.

以上是系統化理解PHP的錯誤和異常的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
php
來源:juejin.im
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板