国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

Eminjannn / 622人閱讀

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

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

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

PHP 錯誤級別

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

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

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

# 用戶級自定義錯誤 可由 trigger_error 觸發(fā) 可由 set_error_handler 捕獲處理
E_USER_ERROR 用戶自定義錯誤 致命錯誤 未處理也會導(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

先看一些問題代碼

天真的想法

1、想關(guān)閉所有的錯誤報告


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

2、想使用 set_error_handler 捕捉錯誤


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

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

官方原話講解:

如果錯誤發(fā)生在腳本執(zhí)行之前(比如文件上傳時),將不會調(diào)用自定義的錯誤處理程序因為它尚未在那時注冊。

再說,退一步講, set_error_handler 是用來自定義用戶級錯誤 E_USER_ERROR & E_USER_WARNING & E_USER_NOTICE & E_USER_DEPRECATED 和 部分運行時系統(tǒng)錯誤 E_WARING & E_NOTICE & E_DEPRECATED 的捕獲器,即語法解析錯誤 E_PARSE (Parse Error) 是無法用其捕獲到的。

官方原話講解:

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

官方原話講解:

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

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

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

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

剖析 PHP 基本的運作機制

其實非常簡單,看一遍就理解了(下文中一些運行機制用詞可能不準(zhǔn)確,還請大佬放過,一切為了讓大家能容易理解)。

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

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

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

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

解析過程:

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

解析完成,語法通過,開始解釋執(zhí)行

執(zhí)行過程:

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

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

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

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

示例:
1、關(guān)閉所有的錯誤報告

main.js


lib.js


那么 lib.php 的任何錯誤都不會被報告出來,因為 main 運行到載入 lib 時,其已向 Zend Engine 發(fā)送了 error_reporting(0); 的指令,所以 lib 中的 Parse Error 不會被報告出來。但這并不是我們想要的,我們要捕獲才對。

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

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


輸出結(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 錯誤,包裝一下輸出給用戶即可。

Parse Error 可以說是用戶級的最高一級錯誤了,Parse Error 了用戶腳本就退出了。

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


運行結(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,
))

如上,語法沒有問題,所以不會有 Parse Error,Zend Engine 開始載入腳本解釋執(zhí)行,因為調(diào)用了不存在的方法,E_ERROR 觸發(fā)后被我們捕獲。

完善的錯誤采集

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

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

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


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

總結(jié)

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

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

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

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/30807.html

相關(guān)文章

  • PHP 完善 Error / Exception 捕獲處理

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

    elliott_hu 評論0 收藏0
  • php error_reporting()關(guān)閉報錯

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

    noONE 評論0 收藏0
  • PHP錯誤、異常匯總

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

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

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

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

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

    LinkedME2016 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<