什麼是錯誤
當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('x<10'); } elseif ($x >= 10 and $x < 100) { throw new LogicException('x>=10 and x<100'); } return $x; } try { echo inverse(2)."n"; } catch (LogicException $e) { echo 'Caught LogicException: ', $e->getMessage(), "n"; } catch (Exception $e) { echo 'Caught Exception: ', $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中的錯誤和異常的詳細內容,更多請關注TW511.COM其它相關文章!