溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Exception、Error Handler的細(xì)節(jié)介紹

發(fā)布時(shí)間:2020-05-13 13:47:04 來(lái)源:億速云 閱讀:245 作者:Leah 欄目:編程語(yǔ)言

今天小編給大家分享的是Exception、Error Handler的細(xì)節(jié)介紹,相信大部分人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,話不多說(shuō),一起往下看吧。

主要函數(shù)

此篇文章重點(diǎn)關(guān)注以下幾個(gè)函數(shù)

1、error_reporting()

2、set_error_handler()

3、set_exception_handler()

4、register_shutdown_function()

5、error_get_last()

以下本文中重點(diǎn)講解問(wèn)題列表:

1、error_reporting() error_get_last() 有什么聯(lián)系?

2、set_error_handler() set_exception_handler() 綁定的handler什么時(shí)候才會(huì)啟動(dòng)? 它們有什么聯(lián)系?

3、register_shutdown_function()通常跟Exception/Error有關(guān)系么?

解疑:

1. error_reporting()error_get_last() 有什么聯(lián)系?

link: php.net - error_reporting()
link: php.net - error_get_last()

a:int error_reporting ([ int $level ] )

大家應(yīng)該再熟悉不過(guò)了, 因此不再贅述.

b:array error_get_last ( void )

獲取最后發(fā)生的錯(cuò)誤

通常用來(lái)獲取PHP運(yùn)行過(guò)程中的Fatal Error錯(cuò)誤(PHP 5).

這兩個(gè)函數(shù)在字面上關(guān)聯(lián)性并不強(qiáng), 但請(qǐng)觀察以下代碼及輸出

<?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()雖然說(shuō)明了獲取最后發(fā)生的錯(cuò)誤, 實(shí)際上也是如此. 但卻沒(méi)有說(shuō)明, 被error_reporting()忽略掉的錯(cuò)誤是否有可能被獲取到, 因此, 當(dāng)我們使用error_get_last()時(shí)需要注意平時(shí)忽略掉的錯(cuò)誤, 如: E_DEPRECATED

2. set_error_handler()set_exception_handler() 綁定的handler什么時(shí)候才會(huì)啟動(dòng)? 它們有什么聯(lián)系?

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 ] )

設(shè)置用戶自定義的錯(cuò)誤處理函數(shù)

通常在PHP腳本運(yùn)行過(guò)程中, 出現(xiàn)一些非中斷性錯(cuò)誤時(shí)觸發(fā).
我們會(huì)用這個(gè)來(lái)記錄錯(cuò)誤日志或直接輸出等操作.

注意:

FALSE: 標(biāo)準(zhǔn)的錯(cuò)誤處理依然會(huì)被執(zhí)行(標(biāo)準(zhǔn)錯(cuò)誤處理根據(jù) display_errors = true/false 決定是否輸出到stderr)

1、參數(shù)$error_types大多設(shè)定為error_reporting(), 但建議設(shè)定為E_ALL, 具體哪些錯(cuò)誤需要被處理, 哪些不需要, 在handler內(nèi)進(jìn)行判斷明顯更加靈活.

2、以下級(jí)別的錯(cuò)誤不能由用戶定義的函數(shù)來(lái)處理: E_ERROR E_PARSE、 E_CORE_ERRORE_CORE_WARNING、 E_COMPILE_ERRORE_COMPILE_WARNING,和在 調(diào)用 set_error_handler() 函數(shù)所在文件中產(chǎn)生的大多數(shù) E_STRICT

3、handler被觸發(fā)后, 并不會(huì)中斷PHP運(yùn)行.

4、bool error_handler ( int $errno , string $errstr [, string $errfile [, int $errline [, array $errcontext ]]] )
注意error_handler的返回值:

b、callable set_exception_handler ( callable $exception_handler )

設(shè)置用戶自定義的異常處理函數(shù)
設(shè)置默認(rèn)的異常處理程序,用于沒(méi)有用 try/catch 塊來(lái)捕獲的異常。 在 exception_handler 調(diào)用后異常會(huì)中止。

注意:

注意點(diǎn)中2, 3項(xiàng)輕描淡寫(xiě)了一下PHP 5/PHP 7之間的不同卻透露出重要的消息(坑..)
PHP 7中, exception_handler 不再只接受Exception了, 并且接收了Error錯(cuò)誤.
link: php.net - PHP7 Errors列表

1、exception_handler 調(diào)用后異常會(huì)中止(腳本終止).

2、PHP 5, PHP 7的exception_handler并不相同.
PHP 5: void handler ( Exception $ex )
PHP 7: void handler ( Throwable $ex )

3、自 PHP 7 以來(lái),大多數(shù)錯(cuò)誤拋出 Error 異常,也能被捕獲。 Error Exception 都實(shí)現(xiàn)了 Throwable 接口。

因此, set_error_handler() set_exception_handler() 之間的關(guān)系也迎刃而解:

PHP 5:

1、set_error_handler(): 負(fù)責(zé)非中斷行錯(cuò)誤.

2、set_exception_handler(): 負(fù)責(zé)沒(méi)有被catch的異常(會(huì)中斷).

3、Fatal Error等: 并不會(huì)被兩者管理, 正常輸出到屏幕上(弊端).

PHP 7:

1、set_error_handler(): 負(fù)責(zé)非中斷行錯(cuò)誤.

2、set_exception_handler(): 負(fù)責(zé)沒(méi)有被catch的異常, Error(會(huì)中斷)

3、Fatal Error等: 由set_exception_handler()管理.

3. register_shutdown_function()通常跟Exception/Error有關(guān)系么?

link: php.net - register_shutdown_function()

注冊(cè)一個(gè) callback ,它會(huì)在腳本執(zhí)行完成或者 exit() 后被調(diào)用。

根據(jù)說(shuō)明可以得出結(jié)論, 它與Exception/Error完全沒(méi)關(guān)系.
提出這個(gè)問(wèn)題, 主要是因?yàn)? 在PHP5中Fatal Error并沒(méi)有明確的接收地點(diǎn), 所以我們通常配合error_get_last()來(lái)接收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的到來(lái), Error已經(jīng)可以被set_exception_handler()捕捉了, 再通過(guò)error_get_last()就多余了. shutdown中更多的是一些版本冗余的工作.

實(shí)例

前言中的需求: 調(diào)試模式下, 將所有錯(cuò)誤提前輸出, 再輸出頁(yè)面內(nèi)容.
以下是demo, 省去了環(huán)境判斷(debug環(huán)境), 大家可以根據(jù)下面這段代碼, 了解本文中所說(shuō)的各種handler的觸發(fā)和調(diào)用情況.

<?php/*
要求: 將所有異常打印在屏幕最上方
*//* Fatal Error 中斷腳本 -> shutdown_handler *///設(shè)置錯(cuò)誤級(jí)別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()); //注冊(cè)錯(cuò)誤處理函數(shù)set_exception_handler('usr_ex_handler'); //注冊(cè)異常處理函數(shù)register_shutdown_function('shutdown_handler');    //注冊(cè)會(huì)在php中止時(shí)執(zhí)行的函數(shù)$global_errors = [];    //用于記錄所有錯(cuò)誤$errnos = [             //錯(cuò)誤級(jí)別
    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']);
    }
}//用戶異常處理函數(shù) (進(jìn)來(lái)就中斷腳本) PHP5只有Exception進(jìn)來(lái)   PHP7Error和Exception//PHP7中 void handler (Throwable $ex) 可捕獲Error和Exception兩種異常, 暫不管//http://php.net/manual/en/language.errors.php7.php PHP7 Error閱讀//內(nèi)部如果有Error則觸發(fā)Error函數(shù), 再回到錯(cuò)誤行繼續(xù)執(zhí)行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 {//針對(duì)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;
}//用戶錯(cuò)誤處理函數(shù)//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;    //如果函數(shù)返回 FALSE,標(biāo)準(zhǔn)錯(cuò)誤處理處理程序?qū)?huì)繼續(xù)調(diào)用。}//用戶PHP終止函數(shù)function shutdown_handler(){
    $content = ob_get_clean();  //讓Exception/Error提前展示
    $err = error_get_last();//檢查一下是否有遺漏掉的錯(cuò)誤 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('這是一個(gè)異常');trigger_error('這是一個(gè)用戶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();//優(yōu)先輸出錯(cuò)誤print_errors('MA ERROR');if (!empty($global_errors)) {    echo END_ERRORS;
}
reset_errors();//輸出正文內(nèi)容echo $content;

看完上述內(nèi)容,你們對(duì)Exception、Error Handler的細(xì)節(jié)介紹大概了解了嗎?如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI