E_ERROR 致命的運行時的致命錯誤,終止程序執行 E_CORE_ERROR PHP 啓動時的致命錯誤 E_COMPILE_ERROR PHP編譯時的致命錯誤 E_USER_ERROR 用戶產生的致命錯誤
Parse Error 編譯時的語法解析錯誤
E_WARNING 運行時警告 (非致命錯誤)。 E_CORE_WARNING PHP初始化啓動過程當中發生的警告 (非致命錯誤) 。 E_COMPILE_WARNING 編譯警告 E_USER_WARNING 用戶產生的警告信息
E_NOTICE 運行時通知。表示腳本遇到可能會表現爲錯誤的狀況. E_USER_NOTICE 用戶產生的通知信息。
set_error_handler($callback);//設置一個用戶的函數(error_handler)來處理腳本中出現的錯誤。
如下級別的錯誤不能由用戶定義的函數來處理:
E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 調用 set_error_handler() 函數所在文件中產生的大多數 E_STRICT。php
也就是:set_error_handler($callback)只能捕獲系統產生的一些Warning、Notice級別的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; } echo $test;//$test未定義,會報一個notice級別的錯誤
輸出結果:閉包
"errno":8 "errstr":Undefined variable: test "errfile":/Users/shuchao/Desktop/handler.php "errline":13
獲取PHP的fatal error,好比記錄到Log裏面,利於咱們分析線上問題,能夠作線上服務的監控。函數
register_shutdown_function($callback)
register_shutdown_function(),就把你要註冊進去的function放進【僞裝是隊列吧】,等到腳本正常退出或顯示調用exit時,再把註冊進去的function拉出來執行.ui
register_shutdown_function()調用的3種狀況:spa
腳本正常退出時;code
在腳本運行(run-time not parse-time)出錯退出時;隊列
用戶調用exit方法退出時。圖片
error_get_last();//函數獲取最後發生的錯誤。
該函數以數組的形式返回最後發生的錯誤。開發
返回的數組包含 4 個鍵和值:
[type] - 錯誤類型
[message] - 錯誤消息
[file] - 發生錯誤所在的文件
[line] - 發生錯誤所在的行
<?php register_shutdown_function( "fatal_handler" ); define('E_FATAL', E_ERROR | E_USER_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR| E_PARSE ); function fatal_handler() { if( $error = error_get_last()) { $errno = $error["type"]; $errfile = $error["file"]; $errline = $error["line"]; $errstr = $error["message"]; $str=<<<EOF "errno":$errno "errstr":$errstr "errfile":$errfile "errline":$errline EOF; //獲取到錯誤能夠本身處理,好比記Log、報警等等 echo $str; } }
在parse-time出錯的時候,是不會調用register_shutdown_function()函數的。只有在run-time出錯的時候,纔會調用register_shutdown_function()。
下面咱們舉例說明:
<?php register_shutdown_function("error_handler"); function error_handler(){ echo "Yeah,it's worked!"; } function test(){} function test(){}
執行結果以下:
Fatal error: Cannot redeclare test() (previously declared in /Users/shuchao/Desktop/error_handler.php:6) in /Users/shuchao/Desktop/error_handler.php on line 7
在執行error_handler.php的時候,因爲重複定義了兩個函數test(),在php的parse-time就出錯了(不是run-time),因此不能回調register_shutdown_function()中的函數。
<?php register_shutdown_function("error_handler"); function error_handler(){ echo "Yeah,it's worked!"; } if(true){ function test(){} } function test(){}
執行結果以下:
Fatal error: Cannot redeclare test() (previously declared in /Users/shuchao/Desktop/error_handler.php:9) in /Users/shuchao/Desktop/error_handler.php on line 7 Yeah,it's worked!%
咱們看到,上面回調了register_shutdown_function().
由於咱們加了一個if()判斷,if()裏面的test()方法,至關於一個閉包,與外面的test()名稱不衝突。
也就是,上面的代碼在parse-time沒有出錯,而是在run-time的時候出錯了,因此咱們可以獲取到fatal error。
<?php register_shutdown_function("error_handler"); function error_handler(){ echo "Yeah,it's worked!"; }
<?php include './error_handler.php'; function test(){} function test(){}
執行 test_error.php的結果以下
Fatal error: Cannot redeclare test() (previously declared in /Users/shuchao/Desktop/test_error.php:3) in /Users/shuchao/Desktop/test_error.php on line 4
當咱們在運行test_error.php的時候,由於redeclare了兩個test()方法,因此php的語法解析器在parse-time的時候就出錯了。 因此不能回調register_shutdown_function()中的方法,不能catch住這個fatal error。
<?php register_shutdown_function("error_handler"); function error_handler(){ echo "Yeah,it's worked!"; }
<?php function test(){} function test(){}
require './error_handler.php'; require './test_error.php';
執行 include_all.php的結果以下
Fatal error: Cannot redeclare test() (previously declared in /Users/shuchao/Desktop/include_all.php:2) in /Users/shuchao/Desktop/include_all.php on line 3 Yeah,it's worked!%
上面咱們捕獲了fatal_error.
由於在運行include_all.php的時候,include_all.php自己語法並無出錯,也就是在parse-time的時候並無出錯,而是include的文件出錯了,也就是在run-time的時候出錯了,這個時候是能回調register_shutdown_function()中的函數的。
<?php register_shutdown_function( "fatal_handler" ); set_error_handler("error_handler"); define('E_FATAL', E_ERROR | E_USER_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR| E_PARSE ); //獲取fatal error function fatal_handler() { $error = error_get_last(); if($error && ($error["type"]===($error["type"] & E_FATAL))) { $errno = $error["type"]; $errfile = $error["file"]; $errline = $error["line"]; $errstr = $error["message"]; error_handler($errno,$errstr,$errfile,$errline); } } //獲取全部的error function error_handler($errno,$errstr,$errfile,$errline){ $str=<<<EOF "errno":$errno "errstr":$errstr "errfile":$errfile "errline":$errline EOF; //獲取到錯誤能夠本身處理,好比記Log、報警等等 echo $str; }
當異常拋出的時候,咱們是想要去捕獲他,並去作處理的。
因此異常常常被當作程序的控制流程使用。
Error是不可恢復的,是在開發過程當中要去解決的。
我想執行insert語句插入一條數據,可能插入失敗(好比ID重複),注意是可能失敗,因此這是一個可能的狀況,也就是異常狀況。
咱們就能夠使用異常來處理這個問題
try { $row->insert(); $inserted = true; } catch (Exception $e) { echo "There was an error inserting the row - ".$e->getMessage(); $inserted = false; } echo "Some more stuff";
假設程序中的有些地方直接throw了異常,沒有進行catch。
咱們如今想要無論在程序的任何一個地方throw異常,即使在throw的地方沒有被catch,咱們也要能catch住,如何作到呢?
//設置默認的異常處理程序,用於沒有用 try/catch 塊來捕獲的異常。 在 exception_handler 調用後異常會停止。 set_exception_handler()
<?php set_exception_handler("my_exception"); function my_exception($exception){ echo $exception->getMessage(); }
<?php require "./exception_handler.php"; throw new Exception("I am Exception");
如今咱們運行 test_exception.php,結果以下:
I am Exception //證實咱們throw的Exception被捕獲了
更多精彩,請關注公衆號「聊聊代碼」,讓咱們一塊兒聊聊「左手代碼右手詩」的事兒。