摘要:重要使命經過十幾天的忙碌,張小五手上的項目終于如期上線,雖然很累,但內心無比的充實與喜悅。對,是不好捕獲。從到對于碼農來說,從到是解決問題的通途,當然張小五也不例外。
重要使命
經過十幾天的忙碌,張小五手上的項目終于如期上線,雖然很累,但內心無比的充實與喜悅。喝了杯熱咖啡,小五在椅子上慵懶地躺著,享受著這份靜謐的時光。
"嗨,小五,這幾天累壞了吧?"
"哈哈,是有點累,不過還好。"
"周末好好休息下吧,我先跟你討論個事兒啊。"
"好的,Z哥。"
"咱們線上運行的代碼,出于各種各樣的情況,可能會有好多Fatal Error、Exception。有沒有辦法,在出現Fatal Error、Exception的時候,咱們能自動捕獲,并寫到Log文件里?"
"嗯...這個嘛,出現Fatal Error的時候,腳本就終止了,不好捕獲啊。"
"對,是不好捕獲。但是對于出現的Fatal Error、Exception我們不知道的話,不能提前發現問題,就像身邊有個隱形的刺客一樣,讓人內心特別虛啊..."
"這樣啊,Z哥,那我這幾天試一下吧!"
"好的,小五,這個挺重要的,相信你!"
"哈哈,Z哥你還是不要抱太大希望,我努力試一下就是了。"
對于碼農來說,從Google到Stackoverflow是解決問題的通途,當然張小五也不例外。
哈!不搜不知道,一搜嚇一跳,PHP還真有捕獲Error和Exception的函數。
//設置一個用戶的函數來處理腳本中出現的錯誤。 set_error_handler($callback) //設置一個用戶的函數來處理腳本中出現的異常。 set_exception_handler($callback)
張小五不自覺的笑了笑:“哈哈,不愧是世界上最好的語言!”
說干就干,看看這兩個函數的威力怎樣,不一會,小五就寫出了測試代碼。
getMessage(); } //拋出異常 throw new Exception("I am Exception");
Yes,拋出的一個Exception真的被捕獲了!
"接下來再測下set_error_handler(),你可不能讓我失望啊!"小五心想。
不錯,Notice級別的錯誤也捕獲到了!
接下來再測一下Fatal Error,如果Fatal Error也能捕獲到,這個需求就實現了!抑制住激動的心情,小五很快寫完了測試代碼。
小五屏住呼吸,等待著奇跡的出現。"咣當",手起指落,幾行報錯躍然屏上...
神馬?Fatal Error竟然沒捕獲到?怎么可能?
正在小五陷入沉思的時候,不經意間,小五瞥見了函數的說明:
以下級別的錯誤不能由用戶定義的函數來處理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 調用 set_error_handler() 函數所在文件中產生的大多數 E_STRICT。
也就是:set_error_handler($callback)只能捕獲系統產生的一些Warning、Notice級別的Error。
嗚呼悲催,好不容易找到了解決辦法,沒想到這函數竟然還是個半吊子,很多級別的錯誤捕獲不到...?
眾里尋他千百度王小五從不是輕言放棄的人,他又繼續搜索,尋找著解決辦法...
"嗯?哈哈,SO上還真有人遇到這問題!"
小五專注地看著答案,邊看邊敲了起來:
要實現這個需求,需要用到兩個函數:register_shutdown_function()和error_get_last()。
register_shutdown_function()register_shutdown_function($callback)register_shutdown_function(),就把你要注冊進去的function放進【假裝是隊列吧】,等到腳本正常退出或顯式調用exit()時,再把注冊進去的function拉出來執行.
register_shutdown_function()調用的3種情況:
腳本正常退出時;
在腳本運行(run-time not parse-time)出錯退出時;
用戶調用exit方法退出時。
error_get_last()error_get_last();//函數獲取最后發生的錯誤。該函數以數組的形式返回最后發生的錯誤。
返回的數組包含 4 個鍵和值:
強烈注意
[type] - 錯誤類型
[message] - 錯誤消息
[file] - 發生錯誤所在的文件
[line] - 發生錯誤所在的行在parse-time出錯的時候,是不會調用register_shutdown_function()函數的。只有在run-time出錯的時候,才會調用register_shutdown_function()。
為了更好的理解,下面我們舉例說明:
NO.1error_handler.php
執行結果如下:
原因分析
在執行error_handler.php的時候,由于重復定義了兩個函數test(),在php的parse-time就出錯了(不是run-time),所以不能回調register_shutdown_function()中注冊的函數。
NO.2error_handler.php
執行結果如下:
原因分析
我們看到,上面回調了register_shutdown_function()中注冊的函數。
NO.3
因為我們加了一個if()判斷,if()里面的test()方法,相當于一個閉包,與外面的test()名稱不沖突。
也就是,上面的代碼在parse-time沒有出錯,而是在run-time的時候出錯了,所以我們能夠獲取到fatal error。error_handler.php
test.php
執行 test.php的結果如下
原因分析
當我們在運行test.php的時候,因為redeclare了兩個test()方法,所以php的語法解析器在parse-time的時候就出錯了。 所以不能回調register_shutdown_function()中的方法,不能catch住這個fatal error。
NO.4error_handler.php
test.php
include_all.php
執行 include_all.php的結果如下
結果分析
上面我們捕獲了fatal_error。
因為在運行include_all.php的時候,include_all.php本身語法并沒有出錯,也就是在parse-time的時候并沒有出錯,而是include的文件出錯了,也就是在run-time的時候出錯了,這個時候是能回調register_shutdown_function()中的函數的。強烈建議:如果我們要使用register_shutdown_function進行錯誤捕捉,使用NO.4,最后一種方法,可以確保錯誤都能捕捉到。
驀然回首解需求"哇塞,原來可以這樣啊!"
王小五按答案中舉的例子認真的敲完代碼,瞬間明白了解決的辦法。真可謂"眾里尋他千百度,驀然回首,那人卻在燈火闌珊處。"小二不自覺的感嘆道!
"好了,我自己就寫一個error_handler腳本吧,確保每次都能獲取到想要的Fatal Error。"
有了這個腳本,我再按SO上說的第四種方法去執行,那這個需求就實現了!
不負眾望王小五興沖沖的找到Z哥,詳細的說明了自己的研究成果。
第二天,小五按照公司現有的框架規則,結合上面的解決辦法,不一會就實現了需求。
"不錯啊,小五,我就說你可以吧!" Z哥高興的說到。
"哈哈,Z哥,這下所有的錯誤都在掌握之中了!"
轉載聲明:本文轉載自「聊聊代碼」,搜索「talkpoem」即可關注。
關注「聊聊代碼」,讓我們一起聊聊“左手代碼右手詩”的事兒。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22892.html
摘要:一中的對象包含了錯誤的具體信息,包括錯誤堆棧等。不源碼了,特別簡單,自己去一下。 一. Error ????JS 中的 Error 對象. 包含了錯誤的具體信息,包括 name、message、錯誤堆棧 stack 等。可以以 new Error 方式創建實例拋出,或調用 Error.captureStackTrace 為已有對象添加 stack 錯誤堆棧信息 而后拋出showImg(...
摘要:上手并過渡到取代的泊學原文鏈接泊學代碼秀視頻自從以來,的錯誤處理幾乎就是一成不變的。在中,這個尷尬的現狀,終于被徹底改變了。無論是還是傳統的,只要類型不匹配約束的時候,就會導致異常。 上手并過渡到PHP7 取代fatal error的engine exceptions 泊學原文鏈接泊學代碼秀視頻 自從PHP 4以來,PHP的錯誤處理幾乎就是一成不變的。只不過在PHP 5.0里添加了E_...
摘要:下的異步嘗試系列下的異步嘗試一初識生成器下的異步嘗試二初識協程下的異步嘗試三協程的版自動執行器下的異步嘗試四版的下的異步嘗試五版的的繼續完善生成器類獲取迭代器當前值獲取迭代器當前值返回當前產生的鍵生成器從上一次處繼續執行重置迭代器向生成器中 PHP下的異步嘗試系列 PHP下的異步嘗試一:初識生成器 PHP下的異步嘗試二:初識協程 PHP下的異步嘗試三:協程的PHP版thunkify自...
先上代碼 ECHO PHP_VERSION.PHP_EOL; function add (int $left,int $right){ return $left+$right; } try { echo add(left, right); } catch (Exception $e) { // Handle exception } catch (Error $e) { //...
閱讀 3222·2021-09-09 11:39
閱讀 1228·2021-09-09 09:33
閱讀 1127·2019-08-30 15:43
閱讀 546·2019-08-29 14:08
閱讀 1733·2019-08-26 13:49
閱讀 2376·2019-08-26 10:09
閱讀 1545·2019-08-23 17:13
閱讀 2283·2019-08-23 12:57