成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP 優(yōu)雅的捕獲處理錯(cuò)誤 -- E_PARSE / E_ERROR

Eminjannn / 633人閱讀

摘要:而后才是一類的運(yùn)行時(shí)錯(cuò)誤。捕獲系統(tǒng)級(jí)錯(cuò)誤首先我們要有一個(gè)容器,讓載入并初始化運(yùn)行時(shí)候,開(kāi)始執(zhí)行。總結(jié)使用捕獲使用捕捉若沒(méi)有做相應(yīng)的處理,則錯(cuò)誤信息會(huì)提交至標(biāo)準(zhǔn)錯(cuò)誤處理流程,根據(jù)的設(shè)定進(jìn)行處理。

開(kāi)發(fā)中使用的框架,大都可以做到優(yōu)雅的回顯出語(yǔ)法級(jí)的錯(cuò)誤,即 Parse Error(syntax error)E_PARSE,此錯(cuò)誤作為面向用戶代碼最底層的錯(cuò)誤如何進(jìn)行捕獲?

下面主要講一下如何捕獲 E_PARSE & E_ERROR 錯(cuò)誤,這里我刻意的把 E_PARSE 錯(cuò)誤放前位的,因?yàn)?E_PARSE 是面向用戶腳本第一位的錯(cuò)誤,即若有必然最先發(fā)生。而后才是 E_ERROR & E_WARNING & E_NOTICE ....一類的運(yùn)行時(shí)錯(cuò)誤。

PHP 錯(cuò)誤級(jí)別

# 系統(tǒng)級(jí)用戶代碼的一些錯(cuò)誤類型 可由 try ... catch ... 捕獲
E_PARSE          解析時(shí)錯(cuò)誤 語(yǔ)法解析錯(cuò)誤 少個(gè)分號(hào) 多個(gè)逗號(hào)一類的 致命錯(cuò)誤
E_ERROR          運(yùn)行時(shí)錯(cuò)誤 比如調(diào)用了未定義的函數(shù)或方法 致命錯(cuò)誤

# 可由 set_error_handler 捕獲處理
E_WARNING        運(yùn)行時(shí)警告 調(diào)用了未定義的變量
E_NOTICE         運(yùn)行時(shí)提醒                  
E_DEPRECATED     運(yùn)行時(shí)已廢棄的函數(shù)或方法

# Zend Engine 相關(guān)的一些錯(cuò)誤 內(nèi)存錯(cuò)誤一類的 應(yīng)該也能通過(guò) try ... catch ... 捕獲 略難測(cè)試
E_CORE_ERROR
E_CORE_WARNING
E_COMPILE_ERROR
E_COMPILE_WARNING

# 用戶級(jí)自定義錯(cuò)誤 可由 trigger_error 觸發(fā) 可由 set_error_handler 捕獲處理
E_USER_ERROR 用戶自定義錯(cuò)誤 致命錯(cuò)誤 未處理也會(huì)導(dǎo)致程序退出
E_USER_WARNING
E_USER_NOTICE
E_USER_DEPRECATED

#編碼標(biāo)準(zhǔn)化警告(建議如何修改以向前兼容)
E_STRICT 部分 捕獲的話 try ... catch ... 部分 set_error_handler
E_RECOVERABLE_ERROR

先看一些問(wèn)題代碼

天真的想法

1、想關(guān)閉所有的錯(cuò)誤報(bào)告


PHP 依然使用自身的錯(cuò)誤機(jī)制報(bào)錯(cuò),原因很簡(jiǎn)單:語(yǔ)法解析 -- 解釋運(yùn)行 -- 結(jié)束退出。當(dāng)腳本最基本的語(yǔ)法存在問(wèn)題時(shí),Zend Engine 自身就會(huì)退出執(zhí)行,并回顯 Parse ERROR 錯(cuò)誤信息。此時(shí)還未解釋執(zhí)行用戶代碼,即 error_reporting(0) 還沒(méi)有在 Zend Engine 中對(duì)運(yùn)行時(shí)做運(yùn)行時(shí)環(huán)境的設(shè)定。

2、想使用 set_error_handler 捕捉錯(cuò)誤


依然得不到理想的結(jié)果。

首先,這段代碼也是在解析階段就報(bào)錯(cuò)了,Parse Error 直接退出了,還沒(méi)有真的執(zhí)行 set_error_handler()。

官方原話講解:

如果錯(cuò)誤發(fā)生在腳本執(zhí)行之前(比如文件上傳時(shí)),將不會(huì)調(diào)用自定義的錯(cuò)誤處理程序因?yàn)樗形丛谀菚r(shí)注冊(cè)。

再說(shuō),退一步講, set_error_handler 是用來(lái)自定義用戶級(jí)錯(cuò)誤 E_USER_ERROR & E_USER_WARNING & E_USER_NOTICE & E_USER_DEPRECATED 和 部分運(yùn)行時(shí)系統(tǒng)錯(cuò)誤 E_WARING & E_NOTICE & E_DEPRECATED 的捕獲器,即語(yǔ)法解析錯(cuò)誤 E_PARSE (Parse Error) 是無(wú)法用其捕獲到的。

官方原話講解:

以下級(jí)別的錯(cuò)誤不能由用戶定義的函數(shù)來(lái)處理: 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 的 handler 最后返回了 false,則此錯(cuò)誤信息會(huì)繼續(xù)被 PHP 的標(biāo)準(zhǔn)錯(cuò)誤處理程序處理:通過(guò) error_reporting 的級(jí)別設(shè)定,該回顯的回顯(display_errors),該寫入錯(cuò)誤日志的寫入錯(cuò)誤日志(log_errors & error_log)

官方原話講解:

重要的是要記住 error_types 里指定的錯(cuò)誤類型都會(huì)繞過(guò) PHP 標(biāo)準(zhǔn)錯(cuò)誤處理程序, 除非回調(diào)函數(shù)返回了 FALSE。

注意,set_error_handler 是有自己的捕獲級(jí)別的,默認(rèn) E_ALL | E_STRICT,不過(guò)要出去上文說(shuō)的那幾個(gè)級(jí)別,且不受 error_reporting() 設(shè)定的級(jí)別影響,即使你 error_reporting(0),set_error_handler 依然能捕捉到相應(yīng)的錯(cuò)誤。

若干問(wèn)題
1、為何很多框架都可以優(yōu)雅的捕獲到語(yǔ)法或致命錯(cuò)誤(E_PARSE & E_ERROR)呢?比如 laravel 標(biāo)配的 whoops 
2、E_PARSE & E_ERROR 到底如何才能捕捉到?
3、以上示例貌似都在說(shuō) E_PARSE & E_ERROR 這種錯(cuò)誤無(wú)法捕獲,那讓用戶來(lái)自定義告警的
error_reporting() 的級(jí)別里為何還有它倆?

既然有相應(yīng)的級(jí)別設(shè)置,那就說(shuō)明是可以被捕捉的,先簡(jiǎn)單說(shuō)明一下,E_ERROR 的捕捉其實(shí)很簡(jiǎn)單,E_PARSE 的捕捉則需解釋和理解一下,會(huì)涉及到 PHP 解析和運(yùn)行腳本的機(jī)制流程。

剖析 PHP 基本的運(yùn)作機(jī)制

其實(shí)非常簡(jiǎn)單,看一遍就理解了(下文中一些運(yùn)行機(jī)制用詞可能不準(zhǔn)確,還請(qǐng)大佬放過(guò),一切為了讓大家能容易理解)。

1、php 在解釋運(yùn)行用戶代碼時(shí),會(huì)以主腳本為載入點(diǎn),Zend Engine 首先對(duì)其進(jìn)行語(yǔ)法解析(Parse),這里一定要理解,Zend Engine 此時(shí)是對(duì)腳本的語(yǔ)法進(jìn)行解析,腳本中的任何 ini 設(shè)置都對(duì)其無(wú)效(還沒(méi)解釋載入執(zhí)行初始化),所以你設(shè)置的什么 error_reporting, display_errors, set_error_handler。只有當(dāng)語(yǔ)法解析無(wú)誤,Zend Engine 開(kāi)始載入并解釋腳本,腳本里的一些參數(shù)設(shè)置項(xiàng)才會(huì)開(kāi)始生效。

2、php 沒(méi)有 //鏈接依賴庫(kù) -- 編譯 -- 運(yùn)行// 一說(shuō)。當(dāng) php 在主腳本中 “引入依賴” 時(shí),Zend Engine 并不會(huì)在對(duì)主腳本做語(yǔ)法解析時(shí)將其 “依賴” 也載入解析。Zend Engine 只會(huì)對(duì)當(dāng)前的主腳本做語(yǔ)法解析,在解析通過(guò)后,便開(kāi)始解釋執(zhí)行用戶代碼,即便 “依賴” 中有 Parse Error,那也得等到真的執(zhí)行到載入命令時(shí)才會(huì)加載解析-解釋-運(yùn)行。

所以,我們首先要構(gòu)建一個(gè) Parse OK 的容器,初始化 Zend Engine 的一些運(yùn)行時(shí)配置,比如關(guān)閉錯(cuò)誤報(bào)告,這樣整個(gè)運(yùn)行時(shí)就是關(guān)閉了錯(cuò)誤報(bào)告的上下文,即便后續(xù)有 E_PAESE & E_ERROR 也不會(huì)回顯錯(cuò)誤信息了。但我們的目的是要捕捉。

使用 try ... catch 捕獲 E_PARSE & E_ERROR

解析過(guò)程:

1:error_reporting(E_ALL); 語(yǔ)法無(wú)誤 繼續(xù)
2:echo "this is main script" . PHP_EOL; 語(yǔ)法無(wú)誤 繼續(xù)
3:require_once __DIR__ . "/lib.php"; 此語(yǔ)法無(wú)誤 繼續(xù)
(注意:此時(shí)并不會(huì)去載入并對(duì) lib.php 做語(yǔ)法解析檢查)
4:echo "hello world!" . PHP_EOL; 語(yǔ)法無(wú)誤繼續(xù)

解析完成,語(yǔ)法通過(guò),開(kāi)始解釋執(zhí)行

執(zhí)行過(guò)程:

1:error_reporting(E_ALL); 將執(zhí)行環(huán)境的錯(cuò)誤告警設(shè)為用戶定義的級(jí)別,運(yùn)行時(shí)用戶上下文已開(kāi)始形成
2:echo "this is main script" . PHP_EOL; 輸出個(gè)字符串
3:require_once __DIR__ . "/lib.php"; 加載未曾載入過(guò)的腳本?開(kāi)始加載執(zhí)行 解析 - 解釋 的流程
4:echo "hello world!" . PHP_EOL; 要在 lib.php 被 解析 - 解釋 完成后才會(huì)回到此處繼續(xù)執(zhí)行

是不是發(fā)現(xiàn)了?在 lib.php 被載入前,main script 的一些運(yùn)行時(shí)的參數(shù)設(shè)置已經(jīng)生效,比如這里的 error_reporting(E_ALL),lib.php 解析/解釋運(yùn)行時(shí)已經(jīng)是在我們自定義好錯(cuò)誤告警級(jí)別的上下文中了,Zend Engine 會(huì)根據(jù)我們?cè)O(shè)定的錯(cuò)誤告警級(jí)別對(duì) lib.php 進(jìn)行載入。這時(shí)就可以明白 E_PARSE & E_ERROR 錯(cuò)誤可被用戶設(shè)定的含義了吧。

即:你首先要有一個(gè)絕對(duì)正確的容器,負(fù)責(zé)將一些必要的用戶設(shè)定傳遞給 Zend Engine 初始化好運(yùn)行時(shí)上下文,此后再載入執(zhí)行的用戶代碼都將在此上下文中執(zhí)行,其后的業(yè)務(wù)邏輯。

合理的代碼組織結(jié)構(gòu)

示例:
1、關(guān)閉所有的錯(cuò)誤報(bào)告

main.js


lib.js


那么 lib.php 的任何錯(cuò)誤都不會(huì)被報(bào)告出來(lái),因?yàn)?main 運(yùn)行到載入 lib 時(shí),其已向 Zend Engine 發(fā)送了 error_reporting(0); 的指令,所以 lib 中的 Parse Error 不會(huì)被報(bào)告出來(lái)。但這并不是我們想要的,我們要捕獲才對(duì)。

2、捕獲系統(tǒng)級(jí)錯(cuò)誤 E_PARSE & E_ERROR

首先我們要有一個(gè)容器,讓 Zend Engine 載入并初始化運(yùn)行時(shí)候,開(kāi)始執(zhí)行。
然后我們可以使用 try ... catch 捕捉錯(cuò)誤,如下:


輸出結(jié)果:

ParseError::__set_state(array(
   "message" => "syntax error, unexpected end of file, expecting "," or ";"",
   "string" => "",
   "code" => 0,
   "file" => "...lib.php",
   "line" => 2,
   "trace" => array (),
   "previous" => NULL,
))

這樣便優(yōu)雅的拿到了 Parse Error 錯(cuò)誤,包裝一下輸出給用戶即可。

Parse Error 可以說(shuō)是用戶級(jí)的最高一級(jí)錯(cuò)誤了,Parse Error 了用戶腳本就退出了。

而后我們才會(huì)可能遇到 E_ERROR & E_WARNING & E_NOTICE & E_DEPRECATED 等,如下:


運(yùn)行結(jié)果

Error::__set_state(array(
    "message"  => "Call to undefined function func_not_exists()",
    "string"   => "",
    "code"     => 0,
    "file"     => "...main.php",
    "line"     => 47,
    "trace"    => array(),
    "previous" => null,
))

如上,語(yǔ)法沒(méi)有問(wèn)題,所以不會(huì)有 Parse Error,Zend Engine 開(kāi)始載入腳本解釋執(zhí)行,因?yàn)檎{(diào)用了不存在的方法,E_ERROR 觸發(fā)后被我們捕獲。

完善的錯(cuò)誤采集

try ... catch 可以捕捉 E_PARSE & E_ERROR

set_error_handler 可以捕捉 E_WARNING & E_NOTICE & E_DEPRECATED & E_USER_*

二者聯(lián)合起來(lái)即可捕捉大部分的用戶代碼層面的錯(cuò)誤


注意 set_error_handler 和 try ... catch 對(duì)錯(cuò)誤捕獲后程序會(huì)繼續(xù)執(zhí)行下去,并不會(huì)立即退出。

總結(jié)

E_ERROR & E_PARSE 使用 try ... catch 捕獲

E_WARNING & E_NOTICE & E_DEPRECATED & E_USER_* 使用 set_error_handler 捕捉

若沒(méi)有做相應(yīng)的處理,則錯(cuò)誤信息會(huì)提交至 PHP 標(biāo)準(zhǔn)錯(cuò)誤處理流程,根據(jù) error_reporting / display_errors / log_errors / error_log 的設(shè)定進(jìn)行處理。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30807.html

相關(guān)文章

  • PHP 完善 Error / Exception 捕獲處理

    摘要:有自身的錯(cuò)誤捕獲級(jí)別,默認(rèn),且不受設(shè)定的級(jí)別的影響。捕獲錯(cuò)誤異常捕獲異常捕獲類型錯(cuò)誤返回值參數(shù)類型不正確嚴(yán)格模式下更容易出現(xiàn)捕獲解析錯(cuò)誤語(yǔ)法錯(cuò)誤除無(wú)法捕獲但除取余可以捕獲很無(wú)奈基本錯(cuò)誤這里要注意的是,在中依然無(wú)法隱式的完美捕獲。 PHP(PHP_VERSION >= 7) 的 Error / Exception 的捕獲與處理還是值得一說(shuō)的,優(yōu)雅處理錯(cuò)誤與異常,在提升框架友好度的同時(shí),也...

    elliott_hu 評(píng)論0 收藏0
  • php error_reporting()關(guān)閉報(bào)錯(cuò)

    摘要:至,有同樣的行為。表示關(guān)閉所有錯(cuò)誤報(bào)告表示顯示二函數(shù)說(shuō)明設(shè)置應(yīng)該報(bào)告何種錯(cuò)誤說(shuō)明函數(shù)能夠在運(yùn)行時(shí)設(shè)置指令。后果是導(dǎo)致腳本終止不再繼續(xù)運(yùn)行。初始化啟動(dòng)過(guò)程中發(fā)生的警告非致命錯(cuò)誤。用戶產(chǎn)少的警告信息。出外的所有錯(cuò)誤和警告信息。 錯(cuò)誤報(bào)告級(jí)別:指定了在什么情況下,腳本代碼中的錯(cuò)誤(這里的錯(cuò)誤是廣義的錯(cuò)誤,包括E_NOTICE注意、E_WARNING警告、E_ERROR致命錯(cuò)誤等)會(huì)以錯(cuò)誤報(bào)告...

    noONE 評(píng)論0 收藏0
  • PHP錯(cuò)誤、異常匯總

    摘要:運(yùn)行時(shí)警告非致命錯(cuò)誤。初始化啟動(dòng)過(guò)程中發(fā)生的警告非致命錯(cuò)誤。表示腳本遇到可能會(huì)表現(xiàn)為錯(cuò)誤的情況用戶產(chǎn)生的通知信息。該函數(shù)以數(shù)組的形式返回最后發(fā)生的錯(cuò)誤。所以異常經(jīng)常被當(dāng)做程序的控制流程使用。在調(diào)用后異常會(huì)中止。 Error Error級(jí)別 Fatal Error:致命錯(cuò)誤(腳本終止運(yùn)行) E_ERROR 致命的運(yùn)行時(shí)的致命錯(cuò)誤,終止程序執(zhí)行 E_CORE_ERROR ...

    yanbingyun1990 評(píng)論0 收藏0
  • php之error_reporting(7)

    摘要:中的參數(shù)就是出錯(cuò)時(shí)顯示中詳解說(shuō)明設(shè)定錯(cuò)誤訊息回報(bào)的等級(jí)。例如用有問(wèn)題的常規(guī)表示法呼叫。通常會(huì)顯示出來(lái),亦會(huì)中斷程式執(zhí)行。意即用這個(gè)遮罩無(wú)法追查到記憶體配置或其它的錯(cuò)誤。從語(yǔ)法中剖析錯(cuò)誤。類似,但不包括核心錯(cuò)誤警告。 value constant 1 E_ERROR 2 E_WARNING 4 E_PARSE 8 E_NOTICE 16 E_CORE_ERROR ...

    khlbat 評(píng)論0 收藏0
  • CodeIgniter3.0+框架自定義異常處理實(shí)現(xiàn)

    摘要:背景框架核心代碼自動(dòng)實(shí)現(xiàn)了異常,并實(shí)現(xiàn)了拋出的對(duì)應(yīng)頁(yè)面和方法,對(duì)于一些個(gè)性化需求特別是接口類型的應(yīng)用,會(huì)不合適。因此需要在不改版核心代碼目錄下文件,來(lái)改變對(duì)異常及等相關(guān)異常的處理。方法說(shuō)明框架比有比較大的改動(dòng),其中之一就是對(duì)異常的處理。 背景 ci3.0框架核心代碼自動(dòng)實(shí)現(xiàn)了異常,并實(shí)現(xiàn)了拋出的對(duì)應(yīng)頁(yè)面和方法,對(duì)于一些個(gè)性化需求特別是接口類型的應(yīng)用,會(huì)不合適。因此需要在不改版核心代碼 ...

    LinkedME2016 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<