摘要:又或者反過來,把錯誤當(dāng)成異常來處理。當(dāng)然,我猜它的目的,應(yīng)該也是為了能實現(xiàn)錯誤與異常之間優(yōu)雅轉(zhuǎn)換而添加的。至此,錯誤與異常的學(xué)習(xí)基本完畢。
這話題已經(jīng)沒有什么新意了,這里只是做做筆記,作為思路的一種整理,也以便后續(xù)忘了可以回來這里查找。
錯誤以下是 PHP 最常見的幾種錯誤:
// E_NOTICE echo $a; // E_WARNING echo 100 / 0; class Sample { public function method() { //not static method } } // E_STRICT Sample::method(); // E_ERROR new Dummy();
運(yùn)行上面代碼,頁面輸出以下信息:
Notice: Undefined variable: a in D:errors-exceptionsdemo4.php on line 6 Warning: Division by zero in D:errors-exceptionsdemo4.php on line 9 Strict Standards: Non-static method Sample::method() should not be called statically in D:errors-exceptionsdemo4.php on line 20 Fatal error: Class "Dummy" not found in D:errors-exceptionsdemo4.php on line 23
在生產(chǎn)環(huán)境下,是不允許把錯誤信息輸出到頁面的。
怎么辦?關(guān)閉錯誤輸出
ini_set("display_errors", 0);
此時,刷新頁面,頁面將不會報任何錯誤。頁面一片空白,或者顯示 500 錯誤。
這也不是我們希望的,雖然不把錯誤輸出到頁面,但是這些錯誤我們是希望把它們都收集起來,寫到日志里面,以便開發(fā)人員能夠不斷改進(jìn)代碼,排查錯誤。
怎么辦?自定義錯誤處理
set_error_handler(function($errno, $errstr, $errfile, $errline) { //在這里對錯誤進(jìn)行處理 echo $errstr . "
"; });
運(yùn)行上面的代碼,頁面輸出:
Undefined variable: a Division by zero Non-static method Sample::method() should not be called statically
很奇怪,不是應(yīng)該輸出 4 個錯誤嗎?怎么 Fatal error 沒有捕捉到。查看 set_error_handler 幫助文檔,我們發(fā)現(xiàn),它有以下描述:
以下級別的錯誤不能由用戶定義的函數(shù)來處理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 調(diào)用 set_error_handler() 函數(shù)所在文件中產(chǎn)生的大多數(shù) E_STRICT。
噢~,原來是這樣,原來 set_error_handler 方法是不能捕捉 E_ERROR 錯誤的(上面的 Fatal error)。那么這類錯誤,我們是不能放過的,也必須捕捉到,并做適當(dāng)?shù)奶幚怼?/p>
怎么辦? 利用 register_shutdown_function 函數(shù)
register_shutdown_function(function() { if(is_null($e = error_get_last()) === false) { echo $e["message"] . "
"; } });
此時,再運(yùn)行上面的例子,頁面會輸出:
Undefined variable: a Division by zero Non-static method Sample::method() should not be called statically Class "Dummy" not found
很好,四種錯誤,我們都成功捕捉了,并按照我們自己的方式進(jìn)行了輸出。
到目前為止,應(yīng)該說能捕捉的 PHP 錯誤,我們都捕捉到了,當(dāng)然還有一些錯誤,壓根就沒有辦法捕捉。比如語法錯誤,這類錯誤是在 PHP 引擎對即將執(zhí)行的文件編譯期間的錯誤。
像上面這種錯誤,程序就沒有辦法捕捉了。只要程序是經(jīng)過測試的,一般不會在生產(chǎn)環(huán)境出現(xiàn)此類錯誤,所以也不用過于但心。
最后注:register_shutdown_function 函數(shù)會在任何導(dǎo)致頁面退出的時候,會被調(diào)用。比如發(fā)生了致命錯誤、使用 exit() 函數(shù)、又或者是頁面執(zhí)行完畢了,都會觸發(fā)該函數(shù)。利用這個特征,我們可以在頁面退出時,獲取到最后一個錯誤,然后進(jìn)行記錄。這個的 “最后一個錯誤” 往往是致命錯誤,原因很簡單:因為一旦錯誤被 set_error_handler 捕捉到了,那么 register_shutdown_function 將捕捉不了。而 前者捕捉不了的,才會被后者捕捉。
異常在 PHP 中,所以異常的基類都是 Exception。異常應(yīng)該說是在 PHP 后來引入了面向?qū)ο蟮母拍詈?,才有的產(chǎn)物。那么說,PHP 原來只拋錯誤,卻沒有異常的概念了。但現(xiàn)在,異常的使用已經(jīng)非常廣泛了,我們有必要學(xué)習(xí)一下。
好,我們來制造一些異常:
new PDO("mysql:dbname=testdb;host=127.0.0.1", "root", "wrong_passwd"); //運(yùn)行結(jié)果 Fatal error: Uncaught exception "PDOException" with message "SQLSTATE[HY000] [1045] Access denied for user "root"@"localhost" (using password: YES)" in D:errors-exceptionsdemo6.php:6 Stack trace: #0 D:errors-exceptionsdemo6.php(6): PDO->__construct("mysql:dbname=te...", "root", "wrong_passwd") #1 {main} thrown in D:errors-exceptionsdemo6.php on line 6再制造一個:
throw new Exception("我是異常"); //運(yùn)行結(jié)果 Fatal error: Uncaught exception "Exception" with message "我是異常" in D:errors-exceptionsdemo6.php:9 Stack trace: #0 {main} thrown in D:errors-exceptionsdemo6.php on line 9在生產(chǎn)環(huán)境下,頁面直接輸出這些異常,同樣是不優(yōu)雅的,那么我們同樣可以像關(guān)閉錯誤輸出一樣,關(guān)閉異常的輸出:
ini_set("display_errors", 0);同樣地,異常雖然不顯示出來了,但是我們需要記錄并處理這些異常。
怎樣做? 使用 set_exception_handler 函數(shù)
set_exception_handler(function($exception) { //在這里,統(tǒng)一處理異常 echo get_class($exception) .": ". $exception->getMessage(); });此時,再運(yùn)行頁面,會輸出以下信息:
PDOException: SQLSTATE[HY000] [1045] Access denied for user "root"@"localhost" (using password: YES)小結(jié)在我剛開始學(xué)習(xí) PHP 的時候,的確被它的錯誤和異常困擾了許久。最開始,我甚至不會用異常。實際上,在現(xiàn)代的 PHP 里面,我們基本上可以完全控制它的異常和錯誤。只需要分開處理就可以了。
擴(kuò)展:我們在實際項目中捕捉并處理異常和錯誤的時候,往往是把兩者合二為一。就是說把異常也當(dāng)成錯誤來處理。又或者反過來,把錯誤當(dāng)成異常來處理。
下面,就讓我們一起看看,如何把兩者相互轉(zhuǎn)換:
把異常轉(zhuǎn)換為錯誤處理
"; } //自定義異常處理 function exceptionHandler($exception) { errorHandler( $exception->getCode(), $exception->getMessage(), $exception->getFile(), $exception->getLine() ); } //自定義致命錯誤處理 function shutdownHandler() { if(is_null($e = error_get_last()) === false) { errorHandler( $e["type"], $e["message"], $e["file"], $e["line"] ); } }不過這樣處理法,會導(dǎo)致異常的堆棧信息“丟失”,意思是無法處理這些堆棧信息了。當(dāng)然是有辦法處理的了,具體請看 demo3.php。
再看看,如何把錯誤轉(zhuǎn)換為異常 (注意:以下代碼僅為了演示其原理,代碼本身并非完全合理):
set_error_handler("errorHandler"); function errorHandler($errno, $errstr, $errfile, $errline) { throw new ErrorException($errstr, $errno, 0, $errfile, $errline); };大家看到,我們使用了 ErrorException 這個類,這是 PHP 后來才引入的,叫作錯誤異常。當(dāng)然,我猜它的目的,應(yīng)該也是為了能實現(xiàn)錯誤與異常之間優(yōu)雅轉(zhuǎn)換而添加的。
至此,錯誤與異常的學(xué)習(xí)基本完畢。最后推薦看看一個網(wǎng)站有關(guān)于對 PHP 錯誤與異常的介紹,尤其是對異常的一些行為的說明,都是值得注意的,網(wǎng)站在這里:PHP - Error & Exception Handling
參考文獻(xiàn)PHP在什么時候應(yīng)該使用異常處理(Exception)?
PHP Trick: Catching fatal errors (E_ERROR) with a custom error handler
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/30299.html
摘要:處理異常是編程非常重要的一點。我們的程序依賴于第三方服務(wù)數(shù)據(jù)庫以及我們的用戶,一切都不可預(yù)料。為了處理這些錯誤,需要添加一個中間件,它有個參數(shù)這樣,我們就可以使用中間件統(tǒng)一處理錯誤了。 譯者按:根據(jù)墨菲定律:有可能出錯的事情,就會出錯。那么,既然代碼必然會出錯,我們就應(yīng)該處理好異常。 原文: How to handle errors in Express 譯者:Fundebug ...
摘要:一旦異常被拋出,就表明錯誤已無法挽回,也不能回來繼續(xù)執(zhí)行。這種在編譯時被強(qiáng)制檢查的異常稱為被檢查的異常。通過獲取原始異常。構(gòu)造器對于在構(gòu)造階段可能會拋出異常,并要求清理的類,最安全的做法是使用嵌套的子句。 點擊進(jìn)入我的博客 Java異常處理的目的在于通過使用少于目前數(shù)量的代碼來簡化大型、可靠的程序的生成,并且通過這種方式可以使你更自信:你的應(yīng)用中沒有未處理的錯誤。 12.1 概念 異...
摘要:當(dāng)運(yùn)行時系統(tǒng)遍歷調(diào)用棧而未找到合適的異常處理器,則運(yùn)行時系統(tǒng)終止。不可查異常編譯器不要求強(qiáng)制處置的異常包括運(yùn)行時異常與其子類和錯誤。 目錄介紹 1.什么是異常 2.異常 2.1 異常的概述和分類【了解】 2.2 JVM默認(rèn)是如何處理異常的【理解】 2.3 異常處理的兩種方式【理解】 2.4 try...catch的方式處理異常【掌握】 2.5 編譯期異常和運(yùn)行期異常的區(qū)別【理解】...
摘要:對異常的處理方法是打印異常的跟蹤棧信息并終止程序運(yùn)行。應(yīng)盡量對異常進(jìn)行適當(dāng)?shù)奶幚?,而不是簡單的將異常跟蹤棧信息打印出來? 一、異常概述 開發(fā)者都希望所有錯誤都能在編譯階段被發(fā)現(xiàn),就是試圖在運(yùn)行程序之前排除所有錯誤,但這是不現(xiàn)實的,余下問題必須在運(yùn)行期間得到解決。 Java將異常分為兩種:CheckedException和RuntimeException。其中,CheckedExcept...
摘要:異常異常的概述和分類異常的概述異常就是程序在運(yùn)行過程中出現(xiàn)的錯誤。運(yùn)行時異常就是程序員所犯的錯誤,需要回來修改代碼。獲取異常類名和異常信息,返回字符串。如果路徑名不同,就是改名并剪切。刪除注意事項中的刪除不走回收站。 1_異常(異常的概述和分類) A:異常的概述 異常就是Java程序在運(yùn)行過程中出現(xiàn)的錯誤。 B:異常的分類 通過API查看Throwable Error 服務(wù)...
閱讀 2720·2021-11-25 09:43
閱讀 750·2021-11-12 10:36
閱讀 5065·2021-11-08 13:18
閱讀 2267·2021-09-06 15:00
閱讀 3235·2019-08-30 15:56
閱讀 1011·2019-08-30 13:57
閱讀 2049·2019-08-30 13:48
閱讀 1478·2019-08-30 11:13