PHP 超實用系列 · 自動捕獲 Fatal Error
重要使命
經過十幾天的忙碌,張小五手上的專案終於如期上線,雖然很累,但內心無比的充實與喜悅。喝了杯熱咖啡,小五在椅子上慵懶地躺著,享受著這份靜謐的時光。
"嗨,小五,這幾天累壞了吧?"
"哈哈,是有點累,不過還好。"
"週末好好休息下吧,我先跟你討論個事兒啊。"
"好的,Z哥。"
"咱們線上執行的程式碼,出於各種各樣的情況,可能會有好多Fatal Error、Exception。有沒有辦法,在出現Fatal Error、Exception的時候,咱們能自動捕獲,並寫到Log檔案裡?"
"嗯...這個嘛,出現Fatal Error的時候,指令碼就終止了,不好捕獲啊。"
"對,是不好捕獲。但是對於出現的Fatal Error、Exception我們不知道的話,不能提前發現問題,就像身邊有個隱形的刺客一樣,讓人內心特別虛啊..."
"好的,小五,這個挺重要的,相信你!"
"哈哈,Z哥你還是不要抱太大希望,我努力試一下就是了。"
從Google到SO
對於碼農來說,從Google到Stackoverflow是解決問題的通途,當然張小五也不例外。
哈!不搜不知道,一搜嚇一跳,PHP還真有捕獲Error和Exception的函式。
//設定一個使用者的函式來處理指令碼中出現的錯誤。
set_error_handler($callback)
//設定一個使用者的函式來處理指令碼中出現的異常。
set_exception_handler($callback)複製程式碼
張小五不自覺的笑了笑:“哈哈,不愧是世界上最好的語言!”
說幹就幹,看看這兩個函式的威力怎樣,不一會,小五就寫出了測試程式碼。
<?php
//設定異常捕獲函式
set_exception_handler("my_exception");
function my_exception($exception){
echo 'Exception Catched:'.$exception->getMessage();
}
//丟擲異常
throw new Exception("I am Exception");複製程式碼
執行結果
Yes,丟擲的一個Exception真的被捕獲了!
"接下來再測下set_error_handler(),你可不能讓我失望啊!"小五心想。
<?php
set_error_handler("error_handler");
function error_handler($errno,$errstr,$errfile,$errline){
$str=<<<EOF
"errno":$errno
"errstr":$errstr
"errfile":$errfile
"errline":$errline
EOF;
//獲取到錯誤可以自己處理,比如記Log、報警等等
echo $str;
}
echo $test;//$test未定義,會報一個notice級別的錯誤複製程式碼
執行結果
不錯,Notice級別的錯誤也捕獲到了!
接下來再測一下Fatal Error,如果Fatal Error也能捕獲到,這個需求就實現了!
抑制住激動的心情,小五很快寫完了測試程式碼。
<?php
set_error_handler("error_handler");
function error_handler($errno,$errstr,$errfile,$errline){
$str=<<<EOF
"errno":$errno
"errstr":$errstr
"errfile":$errfile
"errline":$errline
EOF;
//獲取到錯誤可以自己處理,比如記Log、報警等等
echo $str;
}
//呼叫一個不存在的函式,會出現Fatal Error
test();複製程式碼
小五屏住呼吸,等待著奇蹟的出現。"咣噹",手起指落,幾行報錯躍然屏上...
執行結果神馬?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。
嗚呼悲催,好不容易找到了解決辦法,沒想到這函式竟然還是個半吊子,很多級別的錯誤捕獲不到...