日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

本篇文章給大家介紹一下PHP7使用set_error_handler和set_exception_handler處理異常機制的方法。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。


PHP7如何使用set_error_handler和set_exception_handler處理異常機制


由于歷史原因,php一開始被設計為一門面向過程的語言,所以異常處理沒有使用像Java一樣的 try / catch 機制,出錯時直接顯示到頁面上,或者記錄到web服務器的錯誤日志中,并且php的錯誤分成了很多的級別,例如E_ERROR、E_WARNING、E_PARSE、E_NOTICE等等,對于像E_ERROR、E_PARSE這樣的嚴重錯誤,php會直接終止腳本的運行。

雖然對于php5版本,我們可以使用set_error_handler來注冊自己的錯誤處理方法來代替php的標準錯誤處理方式(輸出到頁面或者記錄到日志),但是一些嚴重錯誤是無法通過這種方式來處理的,具體我們來看手冊對該方法的介紹:

mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )

設置一個用戶的函數(shù)(error_handler)來處理腳本中出現(xiàn)的錯誤。 

本函數(shù)可以用你自己定義的方式來處理運行中的錯誤, 例如,在應用程序中嚴重錯誤發(fā)生時,或者在特定條件下觸發(fā)了一個錯誤(使用 trigger_error()),你需要對數(shù)據(jù)/文件做清理回收。 

重要的是要記住 error_types 里指定的錯誤類型都會繞過 PHP 標準錯誤處理程序, 除非回調函數(shù)返回了 FALSE。 error_reporting() 設置將不會起到作用而你的錯誤處理函數(shù)繼續(xù)會被調用 —— 不過你仍然可以獲取 error_reporting 的當前值,并做適當處理。 需要特別注意的是帶 @ error-control operator 前綴的語句發(fā)生錯誤時,這個值會是 0。 

同時注意,在需要時你有責任使用 die()。 如果錯誤處理程序返回了,腳本將會繼續(xù)執(zhí)行發(fā)生錯誤的后一行。 

以下級別的錯誤不能由用戶定義的函數(shù)來處理:

E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 調用 set_error_handler() 函數(shù)所在文件中產生的大多數(shù) E_STRICT。

手冊上說的很清楚,對于E_ERROR、E_PARSE之類的錯誤并不能被用戶處理,我們來看代碼演示(以下示例用php5.6運行)


<?php  
//自定義的錯誤處理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "錯誤編號errno: $errno<br>";
    echo "錯誤信息errstr: $errstr<br>";
    echo "出錯文件errfile: $errfile<br>";
    echo "出錯行號errline: $errline<br>";
}
set_error_handler('_error_handler', E_ALL | E_STRICT);  // 注冊錯誤處理方法來處理所有錯誤
echo $foo['bar'];  // 由于數(shù)組未定義,會產生一個notice級別的錯誤

運行結果:

錯誤編號errno: 8
錯誤信息errstr: Undefined variable: foo
出錯文件errfile: D:\project\demo\demo.php
出錯行號errline: 16

這時錯誤信息并沒有像往常一樣直接輸出到頁面上,而是按照我們自己的方式來處理了,如果不使用set_error_handler函數(shù),錯誤信息會是常見的這樣展示,當然我們可以關閉掉php的錯誤顯示,這樣錯誤就不會直接顯示到頁面上了。

Notice: Undefined variable: foo in D:\project\demo\demo.php on line 15

這樣的處理機制看似也還不錯,但上面提到不是所有錯誤都可以這樣處理,修改一下上面的代碼如下:

<?php
//自定義的錯誤處理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "錯誤編號errno: $errno<br>";
    echo "錯誤信息errstr: $errstr<br>";
    echo "出錯文件errfile: $errfile<br>";
    echo "出錯行號errline: $errline<br>";
}
set_error_handler('_error_handler', E_ALL | E_STRICT);  // 注冊錯誤處理方法來處理所有錯誤
echo $foo['bar'];  // 由于數(shù)組未定義,會產生一個notice級別的錯誤
trigger_error('人為觸發(fā)一個錯誤', E_USER_ERROR); //人為觸發(fā)錯誤
foobar(3, 5);   //調用未定義的方法將會產生一個Error級別的錯誤

再來運行:

錯誤編號errno: 8
錯誤信息errstr: Undefined variable: foo
出錯文件errfile: D:\project\demo\demo.php
出錯行號errline: 15
錯誤編號errno: 256
錯誤信息errstr: 人為產生觸發(fā)一個錯誤
出錯文件errfile: D:\project\demo\demo.php
出錯行號errline: 17
 
Fatal error: Call to undefined function foobar() in D:\project\demo\demo.php on line 19

正如我們所料,前兩個錯誤被我們“捕獲”處理了,而最后的Fatal error并沒有按照我們注冊的錯誤函數(shù)來處理,還是使用的默認的處理方式,這也是php5版本的錯誤處理的一大缺陷。PHP7之后的異常處理方式有了一些新的變化,來看看手冊上的介紹:

PHP 7 改變了大多數(shù)錯誤的報告方式。不同于傳統(tǒng)(PHP 5)的錯誤報告機制,現(xiàn)在大多數(shù)錯誤被作為 Error 異常拋出。 

這種 Error 異??梢韵?Exception 異常一樣被第一個匹配的 try / catch 塊所捕獲。如果沒有匹配的 catch 塊,則調用異常處理函數(shù)(事先通過 set_exception_handler() 注冊)進行處理。 如果尚未注冊異常處理函數(shù),則按照傳統(tǒng)方式處理:被報告為一個致命錯誤(Fatal Error)。 

Error 類并非繼承自 Exception 類,所以不能用 catch (Exception $e) { ... } 來捕獲 Error。你可以用 catch (Error $e) { ... },或者通過注冊異常處理函數(shù)( set_exception_handler())來捕獲 Error。


php7的這種錯誤處理機制有像java學習的意味,這樣使得我們可以自己來處理大多數(shù)的異常,下面看代碼示例(以下代碼使用php7運行)

<?php
 
//自定義的錯誤處理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "錯誤編號errno: $errno<br>";
    echo "錯誤信息errstr: $errstr<br>";
    echo "出錯文件errfile: $errfile<br>";
    echo "出錯行號errline: $errline<br>";
}
 
set_error_handler('_error_handler', E_ALL | E_STRICT);  // 注冊錯誤處理方法來處理所有錯誤
 
 
try
{
    echo $foo['bar'];  // 由于數(shù)組未定義,會產生一個notice級別的錯誤
 
    trigger_error('人為產生觸發(fā)一個錯誤', E_USER_ERROR); //人為觸發(fā)錯誤
 
    foobar(3, 5);   //調用未定義的方法將會產生一個Error級別的錯誤
}
catch (Error $e)
{
    echo "Error code: " . $e->getCode() . '<br>';
    echo "Error message: " . $e->getMessage() . '<br>';
    echo "Error file: " . $e->getFile() . '<br>';
    echo "Error fileline: " . $e->getLine() . '<br>';
}

運行結果:

錯誤編號errno: 8
錯誤信息errstr: Undefined variable: foo
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 17
錯誤編號errno: 256
錯誤信息errstr: 人為產生觸發(fā)一個錯誤
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 19
Error code: 0
Error message: Call to undefined function foobar()
Error file: E:\project\demo\demo.php
Error fileline: 21

這樣不同類型的錯誤都可以被我們自己處理了,包括致命錯誤。如果不使用 try / catch , php7的報錯信息和php5還是有一些不同:

錯誤編號errno: 8
錯誤信息errstr: Undefined variable: foo
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 17
錯誤編號errno: 256
錯誤信息errstr: 人為觸發(fā)一個錯誤
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 19
 
Fatal error: Uncaught Error: Call to undefined function foobar() in E:\project\demo\demo.php:21 Stack trace: #0 {main} thrown in E:\project\demo\demo.php on line 21

致命錯誤的描述變成: 拋出的一個Error沒有被捕獲。

注意這里的catch限定的只能捕獲Error類的錯誤,并且手冊上明確說了 Error類并不是Exception類的子類,那我同時想捕獲代碼中的Exception錯誤不是做不到了嗎,請看代碼:

<?php
 
//自定義的錯誤處理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "錯誤編號errno: $errno<br>";
    echo "錯誤信息errstr: $errstr<br>";
    echo "出錯文件errfile: $errfile<br>";
    echo "出錯行號errline: $errline<br>";
}
 
set_error_handler('_error_handler', E_ALL | E_STRICT);  // 注冊錯誤處理方法來處理所有錯誤
 
 
try
{
    echo $foo['bar'];  // 由于數(shù)組未定義,會產生一個notice級別的錯誤
 
    trigger_error('人為觸發(fā)一個錯誤', E_USER_ERROR); //人為觸發(fā)錯誤
 
    throw new Exception('This is a exception', 400);  //拋出一個Exception,看是否可以被catch
 
    foobar(3, 5);   //調用未定義的方法將會產生一個Error級別的錯誤
}
catch (Error $e)
{
    echo "Error code: " . $e->getCode() . '<br>';
    echo "Error message: " . $e->getMessage() . '<br>';
    echo "Error file: " . $e->getFile() . '<br>';
    echo "Error fileline: " . $e->getLine() . '<br>';
}

運行結果:

錯誤編號errno: 8
錯誤信息errstr: Undefined variable: foo
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 17
錯誤編號errno: 256
錯誤信息errstr: 人為觸發(fā)一個錯誤
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 19
 
Fatal error: Uncaught Exception: This is a exception in E:\project\demo\demo.php:21 Stack trace: #0 {main} thrown in E:\project\demo\demo.php on line 21

那有沒有什么辦法呢,其實看手冊上的繼承關系圖


PHP7如何使用set_error_handler和set_exception_handler處理異常機制


可以看出,Error類和Exception類都是Throwable的子類(實際上是Error類和Exception類都實現(xiàn)了Throwable接口),所以上面的代碼可以優(yōu)化為:

<?php
 
//自定義的錯誤處理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "錯誤編號errno: $errno<br>";
    echo "錯誤信息errstr: $errstr<br>";
    echo "出錯文件errfile: $errfile<br>";
    echo "出錯行號errline: $errline<br>";
}
 
set_error_handler('_error_handler', E_ALL | E_STRICT);  // 注冊錯誤處理方法來處理所有錯誤
 
 
try
{
    echo $foo['bar'];  // 由于數(shù)組未定義,會產生一個notice級別的錯誤
 
    trigger_error('人為觸發(fā)一個錯誤', E_USER_ERROR); //人為觸發(fā)錯誤
 
    if (mt_rand(1, 10) > 5)
    {
        throw new Exception('This is a exception', 400);  //拋出一個Exception,看是否可以被catch
    }
    else
    {
        foobar(3, 5);   //調用未定義的方法將會產生一個Error級別的錯誤
    }
}
catch (Throwable $e)
{
    echo "Error code: " . $e->getCode() . '<br>';
    echo "Error message: " . $e->getMessage() . '<br>';
    echo "Error file: " . $e->getFile() . '<br>';
    echo "Error fileline: " . $e->getLine() . '<br>';
}

多次運行可以看到,不管是Exception異常還是Error異常,都可以被捕獲處理了。

如果不想所有的錯誤都用 try / catch 處理,還可以使用set_exception_handler注冊異常處理函數(shù),這樣當有未被catch的異常產生時,系統(tǒng)會為我們自動調用注冊的處理函數(shù)來處理。

<?php
 
//自定義的錯誤處理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "錯誤編號errno: $errno<br>";
    echo "錯誤信息errstr: $errstr<br>";
    echo "出錯文件errfile: $errfile<br>";
    echo "出錯行號errline: $errline<br>";
}
 
set_error_handler('_error_handler', E_ALL | E_STRICT);  // 注冊錯誤處理方法來處理所有錯誤
 
function _exception_handler(Throwable $e)
{
    if ($e instanceof Error)
    {
        echo "catch Error: " . $e->getCode() . '   ' . $e->getMessage() . '<br>';
    }
    else
    {
        echo "catch Exception: " . $e->getCode() . '   ' . $e->getMessage() . '<br>';
    }
}
 
set_exception_handler('_exception_handler');    // 注冊異常處理方法來捕獲異常
 
 
echo $foo['bar'];  // 由于數(shù)組未定義,會產生一個notice級別的錯誤
 
trigger_error('人為觸發(fā)一個錯誤', E_USER_ERROR); //人為觸發(fā)錯誤
 
if (mt_rand(1, 10) > 5)
{
    throw new Exception('This is a exception', 400);  //拋出一個Exception,看是否可以被catch
}
else
{
    foobar(3, 5);   //調用未定義的方法將會產生一個Error級別的錯誤
}
錯誤編號errno: 8
錯誤信息errstr: Undefined variable: foo
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 29
錯誤編號errno: 256
錯誤信息errstr: 人為觸發(fā)一個錯誤
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 31
catch Error: 0 Call to undefined function foobar()
 
 
錯誤編號errno: 8
錯誤信息errstr: Undefined variable: foo
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 29
錯誤編號errno: 256
錯誤信息errstr: 人為觸發(fā)一個錯誤
出錯文件errfile: E:\project\demo\demo.php
出錯行號errline: 31
catch Exception: 400 This is a exception

這時我們可能又會被PHP7弄暈,哪些被set_error_handler處理,哪些被set_exception_handler處理,手冊上也沒有明確說明這塊,根據(jù)我的總結,大致上不會導致腳本終止運行的錯誤會被set_error_handler處理,而會終止腳本運行的嚴重錯誤會被當作Error拋出,但不是絕對,上面人為觸發(fā)的

E_USER_ERROR就是一個會打斷腳本運行的錯誤,但是并沒有當作Error異常拋出,而是交由set_error_handler注冊的方法處理,這可能是因為這類錯誤是我們自己人為產生的有關,所以PHP7的錯誤處理還是有一些含糊不清,對于我們自己處理時要多加小心。


分享到:
標簽:PHP7 set_error_handler 處理異常機制
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定