前幾天公司平臺接入了新的合做商,數據抓取服務一直沒問題,到今天有一本書一直報錯,查看log發現Warning,出錯是因爲致使xml解析錯誤。想到輸出一下具體的bookid和chapter_id來查看究竟是哪本書哪一個章節的問題。php
直接想到的方案是try catch在出錯的時候輸出bookid和chapter_id,可是發現php try catch沒法處理Warning錯誤,因而Google了php如何catch warning,在stackoverflow上找到了以下方法:http://stackoverflow.com/questions/1241728/can-i-try-catch-a-warning數組
大體的意思是經過 set_error_handler來自定義處理Warning的方法,在其中拋出一個異常而後再try catch它輸出bookid和chapter_id,基本照抄給的實例因而以下的代碼:函數
phpset_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) { // error was suppressed with the @-operator if (0 === error_reporting()) { return false; } throw new ErrorException($errstr, 0, $errno, $errfile, $errline); }, E_WARNING); try{ $chapter_content = simplexml_load_string($chaptercontent_xml); } catch (Exception $e) { echo "Caught exception: bookid = $id , chapter_id = $chapter_id ", $e->getMessage(), "\n"; exit(); } restore_error_handler();
解釋:使用set_error_handler來接管warning的處理,在其回調函數中拋出一個Exception,而後就能夠try catch了,最後調用restore_error_handler();來撤銷你設置的error_handler從而使其不影響後續的代碼。rest
思考:這樣改完後確實獲得了bookid和chapter_id,可是有沒有別的更簡單方法來實現,其實我最本質的需求就是要自定義輸出的Warning消息使其在輸出錯誤的時候帶上bookid和chapter_id上面的方法雖然解決了這個問題可是繞了一個大圈。查看php手冊上set_error_handler的詳細用法發現:code
errcontext
第五個可選參數, errcontext, 是一個指向錯誤發生時活動符號表的 array。 也就是說,errcontext 會包含錯誤觸發處做用域內全部變量的數組。 用戶的錯誤處理程序不該該修改錯誤上下文(context)。xml
咱們在此處直接用errcontext直接輸出要的信息便可,因而有了下面的代碼:作用域
phpset_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext){ // error was suppressed with the @-operator if (0 === error_reporting()) { return false; } echo "Caught Waring:bookid=$errcontext[bookid],chapter_id=$errcontext[chapter_id] Waring Message:",$errstr,' in ',$errfile,' on line ',$errline,"\n"; }, E_WARNING); $chapter_content = simplexml_load_string($chaptercontent_xml); restore_error_handler();
解釋:直接在set_error_handler組織和輸出錯誤信息便可完成自定義Warning錯誤信息的輸出,這樣簡單了不少,加上這段代碼後之後若是出問題直接去log裏面查找就可拿到所需的信息,定位到問題所在。get
總結:在解決完一個問題是最好多想一想這個問題的本質,有沒有更好的解決方案,這才能不斷進步。回調函數