您好,登錄后才能下訂單哦!
今天小編給大家分享的是Exception、Error Handler的細節介紹,相信大部分人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,話不多說,一起往下看吧。
主要函數
此篇文章重點關注以下幾個函數
1、error_reporting()
2、set_error_handler()
3、set_exception_handler()
4、register_shutdown_function()
5、error_get_last()
以下本文中重點講解問題列表:
1、error_reporting()
與 error_get_last()
有什么聯系?
2、set_error_handler()
與 set_exception_handler()
綁定的handler
什么時候才會啟動? 它們有什么聯系?
3、register_shutdown_function()
通常跟Exception/Error
有關系么?
解疑:
1. error_reporting()
與 error_get_last()
有什么聯系?
link: php.net - error_reporting()
link: php.net - error_get_last()
a:int error_reporting ([ int $level ] )
大家應該再熟悉不過了, 因此不再贅述.
b:array error_get_last ( void )
獲取最后發生的錯誤
通常用來獲取PHP運行過程中的Fatal Error錯誤(PHP 5).
這兩個函數在字面上關聯性并不強, 但請觀察以下代碼及輸出
<?php error_reporting(E_ALL & ~E_NOTICE); $a = $b; //E_NOTICEprint_r(error_get_last());/* output: Array ( [type] => 8 [message] => Undefined variable: b [file] => /app/t.php [line] => 3 ) */
error_get_last()
雖然說明了獲取最后發生的錯誤, 實際上也是如此. 但卻沒有說明, 被error_reporting()
忽略掉的錯誤是否有可能被獲取到, 因此, 當我們使用error_get_last()
時需要注意平時忽略掉的錯誤, 如: E_DEPRECATED
2. set_error_handler()
與 set_exception_handler()
綁定的handler
什么時候才會啟動? 它們有什么聯系?
link: php.net - set_error_handler()
link: php.net - set_exception_handler()
a、mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )
設置用戶自定義的錯誤處理函數
通常在PHP腳本運行過程中, 出現一些非中斷性錯誤時觸發.
我們會用這個來記錄錯誤日志或直接輸出等操作.
注意:
FALSE: 標準的錯誤處理依然會被執行(標準錯誤處理根據 display_errors = true/false
決定是否輸出到stderr
)
1、參數$error_types
大多設定為error_reporting()
, 但建議設定為E_ALL
, 具體哪些錯誤需要被處理, 哪些不需要, 在handler內進行判斷明顯更加靈活.
2、以下級別的錯誤不能由用戶定義的函數來處理: E_ERROR
、 E_PARSE
、 E_CORE_ERROR
、 E_CORE_WARNING
、 E_COMPILE_ERROR
、 E_COMPILE_WARNING
,和在 調用 set_error_handler()
函數所在文件中產生的大多數 E_STRICT
3、handler被觸發后, 并不會中斷PHP運行.
4、bool error_handler ( int $errno , string $errstr [, string $errfile [, int $errline [, array $errcontext ]]] )
注意error_handler
的返回值:
b、callable set_exception_handler ( callable $exception_handler )
設置用戶自定義的異常處理函數
設置默認的異常處理程序,用于沒有用 try
/catch
塊來捕獲的異常。 在 exception_handler
調用后異常會中止。
注意:
注意點中2, 3項輕描淡寫了一下PHP 5/PHP 7之間的不同卻透露出重要的消息(坑..)
PHP 7中, exception_handler
不再只接受Exception
了, 并且接收了Error
錯誤.
link: php.net - PHP7 Errors
列表
1、exception_handler
調用后異常會中止(腳本終止).
2、PHP 5, PHP 7的exception_handler
并不相同.
PHP 5: void handler ( Exception $ex )
PHP 7: void handler ( Throwable $ex )
3、自 PHP 7 以來,大多數錯誤拋出 Error
異常,也能被捕獲。 Error
和 Exception
都實現了 Throwable 接口。
因此, set_error_handler()
與 set_exception_handler()
之間的關系也迎刃而解:
PHP 5:
1、set_error_handler()
: 負責非中斷行錯誤.
2、set_exception_handler()
: 負責沒有被catch的異常(會中斷).
3、Fatal Error
等: 并不會被兩者管理, 正常輸出到屏幕上(弊端).
PHP 7:
1、set_error_handler()
: 負責非中斷行錯誤.
2、set_exception_handler()
: 負責沒有被catch的異常, Error(會中斷)
3、Fatal Error
等: 由set_exception_handler()
管理.
3. register_shutdown_function()
通常跟Exception
/Error
有關系么?
link: php.net - register_shutdown_function()
注冊一個 callback ,它會在腳本執行完成或者 exit() 后被調用。
根據說明可以得出結論, 它與Exception
/Error
完全沒關系.
提出這個問題, 主要是因為, 在PHP5中Fatal Error
并沒有明確的接收地點, 所以我們通常配合error_get_last()
來接收Fatal Error
<?php register_shutdown_function('shutdown_function'); unknown_function();function shutdown_function() { print_r(error_get_last()); }/* output:Array( [type] => 1 [message] => Uncaught Error: Call to undefined function unknown_function() in /app/t.php:3Stack trace:#0 {main} thrown [file] => /app/t.php [line] => 3) */
然而隨著PHP 7的到來, Error已經可以被set_exception_handler()
捕捉了, 再通過error_get_last()
就多余了. shutdown中更多的是一些版本冗余的工作.
實例
前言中的需求: 調試模式下, 將所有錯誤提前輸出, 再輸出頁面內容.
以下是demo, 省去了環境判斷(debug環境), 大家可以根據下面這段代碼, 了解本文中所說的各種handler的觸發和調用情況.
<?php/* 要求: 將所有異常打印在屏幕最上方 *//* Fatal Error 中斷腳本 -> shutdown_handler *///設置錯誤級別define("END_ERRORS", '--END ERRORS--' . PHP_EOL . PHP_EOL); ini_set('display_errors', true); ini_set('error_reporting', E_ALL & ~E_DEPRECATED); set_error_handler('usr_err_handler', error_reporting()); //注冊錯誤處理函數set_exception_handler('usr_ex_handler'); //注冊異常處理函數register_shutdown_function('shutdown_handler'); //注冊會在php中止時執行的函數$global_errors = []; //用于記錄所有錯誤$errnos = [ //錯誤級別 0 => 'ERROR',//PHP7 ERROR的CODE 1 => 'E_ERROR',//FATAL ERROR(PHP5), E_ERROR 2 => 'E_WARNING', 4 => 'E_PARSE', 8 => 'E_NOTICE', 16 => 'E_CORE_ERROR', 32 => 'E_CORE_WARNING', 64 => 'E_COMPILE_ERROR', 128 => 'E_COMPILE_WARNING', 256 => 'E_USER_ERROR', 512 => 'E_USER_WARNING', 1024 => 'E_USER_NOTICE', 2048 => 'E_STRICT', 4096 => 'E_RECOVERABLE_ERROR', 8192 => 'E_DEPRECATED', 16384 => 'E_USER_DEPRECATED', 30719 => 'E_ALL', ];function reset_errors(){ global $global_errors; $global_errors = []; }function get_errnostr($errno){ global $errnos; return $errnos[$errno]; }function set_errnos($errno, $errstr){ global $global_errors; $global_errors[] = [ 'errno' => $errno, 'errnostr' => get_errnostr($errno), 'errstr' => $errstr, ]; }function print_errors($prefix){ global $global_errors; foreach ($global_errors as $err) {//由于handler中依然有可能有error 因此放最后 printf("[%s]: %s, %d, %s\n", $prefix, $err['errnostr'], $err['errno'], $err['errstr']); } }//用戶異常處理函數 (進來就中斷腳本) PHP5只有Exception進來 PHP7Error和Exception//PHP7中 void handler (Throwable $ex) 可捕獲Error和Exception兩種異常, 暫不管//http://php.net/manual/en/language.errors.php7.php PHP7 Error閱讀//內部如果有Error則觸發Error函數, 再回到錯誤行繼續執行function usr_ex_handler($ex){ $content = ob_get_clean(); //讓Exception/Error提前展示 print_errors('EX ERROR'); reset_errors(); $errnostr = get_errnostr($ex->getCode()); $errno = $ex->getCode(); $errstr = $ex->getMessage(); if ($ex instanceof Exception) { printf("[EXCEPTION]: %s, %d, %s\n", $errnostr, $errno, $errstr); } else {//針對PHP7 $ex instanceof Error printf("[EX FATAL ERROR]: %s, %d, %s\n", $errnostr, $errno, $errstr); } //由于handler中依然有可能有error 因此放最后 print_errors('EX ERROR'); reset_errors(); echo END_ERRORS; echo $content; return; }//用戶錯誤處理函數//E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING不能被用戶處理function usr_err_handler($errno, $errstr, $errfile, $errline, $errcontext){ set_errnos($errno, $errstr); return true; //如果函數返回 FALSE,標準錯誤處理處理程序將會繼續調用。}//用戶PHP終止函數function shutdown_handler(){ $content = ob_get_clean(); //讓Exception/Error提前展示 $err = error_get_last();//檢查一下是否有遺漏掉的錯誤 php5 fatal error if ($err['type'] & error_reporting()) { set_errnos($err['type'], $err['message']); } print_errors('ST ERROR'); reset_errors(); echo $content; } ob_start();echo 'Main function...', PHP_EOL;//搞事情//throw new Exception('這是一個異常');trigger_error('這是一個用戶error');//E_USER_NOTICEif (version_compare(PHP_VERSION, '7.0.0') >= 0) { mcrypt_encrypt();//E_WARNING, E_DEPRECATED} else { mysql(); } unknown_function(); //fatal error$content = ob_get_clean();//優先輸出錯誤print_errors('MA ERROR');if (!empty($global_errors)) { echo END_ERRORS; } reset_errors();//輸出正文內容echo $content;
看完上述內容,你們對Exception、Error Handler的細節介紹大概了解了嗎?如果想了解更多相關文章內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。