成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

如何處理 PHP 的錯(cuò)誤與異常(筆記)

kyanag / 2316人閱讀

摘要:又或者反過(guò)來(lái),把錯(cuò)誤當(dāng)成異常來(lái)處理。當(dāng)然,我猜它的目的,應(yīng)該也是為了能實(shí)現(xiàn)錯(cuò)誤與異常之間優(yōu)雅轉(zhuǎn)換而添加的。至此,錯(cuò)誤與異常的學(xué)習(xí)基本完畢。

這話(huà)題已經(jīng)沒(méi)有什么新意了,這里只是做做筆記,作為思路的一種整理,也以便后續(xù)忘了可以回來(lái)這里查找。

錯(cuò)誤

以下是 PHP 最常見(jiàn)的幾種錯(cuò)誤:

// E_NOTICE
echo $a;

// E_WARNING
echo 100 / 0;

class Sample
{
    public function method()
    {
        //not static method
    }
}

// E_STRICT
Sample::method();

// E_ERROR
new Dummy();

運(yùn)行上面代碼,頁(yè)面輸出以下信息:

Notice: Undefined variable: a in D:errors-exceptionsdemo4.php on line 6

Warning: Division by zero in D:errors-exceptionsdemo4.php on line 9

Strict Standards: Non-static method Sample::method() should not be called statically in D:errors-exceptionsdemo4.php on line 20

Fatal error: Class "Dummy" not found in D:errors-exceptionsdemo4.php on line 23

在生產(chǎn)環(huán)境下,是不允許把錯(cuò)誤信息輸出到頁(yè)面的。

怎么辦?關(guān)閉錯(cuò)誤輸出

ini_set("display_errors", 0);

此時(shí),刷新頁(yè)面,頁(yè)面將不會(huì)報(bào)任何錯(cuò)誤。頁(yè)面一片空白,或者顯示 500 錯(cuò)誤。

這也不是我們希望的,雖然不把錯(cuò)誤輸出到頁(yè)面,但是這些錯(cuò)誤我們是希望把它們都收集起來(lái),寫(xiě)到日志里面,以便開(kāi)發(fā)人員能夠不斷改進(jìn)代碼,排查錯(cuò)誤。

怎么辦?自定義錯(cuò)誤處理

set_error_handler(function($errno, $errstr, $errfile, $errline) {

    //在這里對(duì)錯(cuò)誤進(jìn)行處理

    echo $errstr . "
"; });

運(yùn)行上面的代碼,頁(yè)面輸出:

Undefined variable: a
Division by zero
Non-static method Sample::method() should not be called statically

很奇怪,不是應(yīng)該輸出 4 個(gè)錯(cuò)誤嗎?怎么 Fatal error 沒(méi)有捕捉到。查看 set_error_handler 幫助文檔,我們發(fā)現(xiàn),它有以下描述:

以下級(jí)別的錯(cuò)誤不能由用戶(hù)定義的函數(shù)來(lái)處理: 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。

噢~,原來(lái)是這樣,原來(lái) set_error_handler 方法是不能捕捉 E_ERROR 錯(cuò)誤的(上面的 Fatal error)。那么這類(lèi)錯(cuò)誤,我們是不能放過(guò)的,也必須捕捉到,并做適當(dāng)?shù)奶幚怼?/p>

怎么辦? 利用 register_shutdown_function 函數(shù)

register_shutdown_function(function() {

    if(is_null($e = error_get_last()) === false) {

        echo $e["message"] . "
"; } });

此時(shí),再運(yùn)行上面的例子,頁(yè)面會(huì)輸出:

Undefined variable: a
Division by zero
Non-static method Sample::method() should not be called statically
Class "Dummy" not found

很好,四種錯(cuò)誤,我們都成功捕捉了,并按照我們自己的方式進(jìn)行了輸出。

到目前為止,應(yīng)該說(shuō)能捕捉的 PHP 錯(cuò)誤,我們都捕捉到了,當(dāng)然還有一些錯(cuò)誤,壓根就沒(méi)有辦法捕捉。比如語(yǔ)法錯(cuò)誤,這類(lèi)錯(cuò)誤是在 PHP 引擎對(duì)即將執(zhí)行的文件編譯期間的錯(cuò)誤。


像上面這種錯(cuò)誤,程序就沒(méi)有辦法捕捉了。只要程序是經(jīng)過(guò)測(cè)試的,一般不會(huì)在生產(chǎn)環(huán)境出現(xiàn)此類(lèi)錯(cuò)誤,所以也不用過(guò)于但心。

最后注:register_shutdown_function 函數(shù)會(huì)在任何導(dǎo)致頁(yè)面退出的時(shí)候,會(huì)被調(diào)用。比如發(fā)生了致命錯(cuò)誤、使用 exit() 函數(shù)、又或者是頁(yè)面執(zhí)行完畢了,都會(huì)觸發(fā)該函數(shù)。利用這個(gè)特征,我們可以在頁(yè)面退出時(shí),獲取到最后一個(gè)錯(cuò)誤,然后進(jìn)行記錄。這個(gè)的 “最后一個(gè)錯(cuò)誤” 往往是致命錯(cuò)誤,原因很簡(jiǎn)單:因?yàn)橐坏╁e(cuò)誤被 set_error_handler 捕捉到了,那么 register_shutdown_function 將捕捉不了。而 前者捕捉不了的,才會(huì)被后者捕捉。

異常

在 PHP 中,所以異常的基類(lèi)都是 Exception。異常應(yīng)該說(shuō)是在 PHP 后來(lái)引入了面向?qū)ο蟮母拍詈?,才有的產(chǎn)物。那么說(shuō),PHP 原來(lái)只拋錯(cuò)誤,卻沒(méi)有異常的概念了。但現(xiàn)在,異常的使用已經(jīng)非常廣泛了,我們有必要學(xué)習(xí)一下。

好,我們來(lái)制造一些異常:

new PDO("mysql:dbname=testdb;host=127.0.0.1", "root", "wrong_passwd");

//運(yùn)行結(jié)果
Fatal error: Uncaught exception "PDOException" with message "SQLSTATE[HY000] [1045] Access denied for user "root"@"localhost" (using password: YES)" in D:errors-exceptionsdemo6.php:6 Stack trace: #0 D:errors-exceptionsdemo6.php(6): PDO->__construct("mysql:dbname=te...", "root", "wrong_passwd") #1 {main} thrown in D:errors-exceptionsdemo6.php on line 6

再制造一個(gè):

throw new Exception("我是異常");

//運(yùn)行結(jié)果
Fatal error: Uncaught exception "Exception" with message "我是異常" in D:errors-exceptionsdemo6.php:9 Stack trace: #0 {main} thrown in D:errors-exceptionsdemo6.php on line 9

在生產(chǎn)環(huán)境下,頁(yè)面直接輸出這些異常,同樣是不優(yōu)雅的,那么我們同樣可以像關(guān)閉錯(cuò)誤輸出一樣,關(guān)閉異常的輸出:

ini_set("display_errors", 0);

同樣地,異常雖然不顯示出來(lái)了,但是我們需要記錄并處理這些異常。

怎樣做? 使用 set_exception_handler 函數(shù)

set_exception_handler(function($exception) {

    //在這里,統(tǒng)一處理異常
    
    echo get_class($exception) .": ". $exception->getMessage();
});

此時(shí),再運(yùn)行頁(yè)面,會(huì)輸出以下信息:

PDOException: SQLSTATE[HY000] [1045] Access denied for user "root"@"localhost" (using password: YES)
小結(jié)

在我剛開(kāi)始學(xué)習(xí) PHP 的時(shí)候,的確被它的錯(cuò)誤和異常困擾了許久。最開(kāi)始,我甚至不會(huì)用異常。實(shí)際上,在現(xiàn)代的 PHP 里面,我們基本上可以完全控制它的異常和錯(cuò)誤。只需要分開(kāi)處理就可以了。

擴(kuò)展:我們?cè)趯?shí)際項(xiàng)目中捕捉并處理異常和錯(cuò)誤的時(shí)候,往往是把兩者合二為一。就是說(shuō)把異常也當(dāng)成錯(cuò)誤來(lái)處理。又或者反過(guò)來(lái),把錯(cuò)誤當(dāng)成異常來(lái)處理。

下面,就讓我們一起看看,如何把兩者相互轉(zhuǎn)換:

把異常轉(zhuǎn)換為錯(cuò)誤處理

";
}

//自定義異常處理
function exceptionHandler($exception) {
    errorHandler(
        $exception->getCode(),
        $exception->getMessage(),
        $exception->getFile(),
        $exception->getLine()
    );
}

//自定義致命錯(cuò)誤處理
function shutdownHandler() {
    if(is_null($e = error_get_last()) === false) {
        errorHandler(
            $e["type"],
            $e["message"],
            $e["file"],
            $e["line"]
        );
    }
}

不過(guò)這樣處理法,會(huì)導(dǎo)致異常的堆棧信息“丟失”,意思是無(wú)法處理這些堆棧信息了。當(dāng)然是有辦法處理的了,具體請(qǐng)看 demo3.php。

再看看,如何把錯(cuò)誤轉(zhuǎn)換為異常 (注意:以下代碼僅為了演示其原理,代碼本身并非完全合理)

set_error_handler("errorHandler");

function errorHandler($errno, $errstr, $errfile, $errline) {
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
};

大家看到,我們使用了 ErrorException 這個(gè)類(lèi),這是 PHP 后來(lái)才引入的,叫作錯(cuò)誤異常。當(dāng)然,我猜它的目的,應(yīng)該也是為了能實(shí)現(xiàn)錯(cuò)誤與異常之間優(yōu)雅轉(zhuǎn)換而添加的。

至此,錯(cuò)誤與異常的學(xué)習(xí)基本完畢。最后推薦看看一個(gè)網(wǎng)站有關(guān)于對(duì) PHP 錯(cuò)誤與異常的介紹,尤其是對(duì)異常的一些行為的說(shuō)明,都是值得注意的,網(wǎng)站在這里:PHP - Error & Exception Handling

參考文獻(xiàn)

PHP在什么時(shí)候應(yīng)該使用異常處理(Exception)?

PHP Trick: Catching fatal errors (E_ERROR) with a custom error handler

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30299.html

相關(guān)文章

  • 何處Express異常?

    摘要:處理異常是編程非常重要的一點(diǎn)。我們的程序依賴(lài)于第三方服務(wù)數(shù)據(jù)庫(kù)以及我們的用戶(hù),一切都不可預(yù)料。為了處理這些錯(cuò)誤,需要添加一個(gè)中間件,它有個(gè)參數(shù)這樣,我們就可以使用中間件統(tǒng)一處理錯(cuò)誤了。 譯者按:根據(jù)墨菲定律:有可能出錯(cuò)的事情,就會(huì)出錯(cuò)。那么,既然代碼必然會(huì)出錯(cuò),我們就應(yīng)該處理好異常。 原文: How to handle errors in Express 譯者:Fundebug ...

    justjavac 評(píng)論0 收藏0
  • 《Java編程思想》筆記12.通過(guò)異常錯(cuò)誤

    摘要:一旦異常被拋出,就表明錯(cuò)誤已無(wú)法挽回,也不能回來(lái)繼續(xù)執(zhí)行。這種在編譯時(shí)被強(qiáng)制檢查的異常稱(chēng)為被檢查的異常。通過(guò)獲取原始異常。構(gòu)造器對(duì)于在構(gòu)造階段可能會(huì)拋出異常,并要求清理的類(lèi),最安全的做法是使用嵌套的子句。 點(diǎn)擊進(jìn)入我的博客 Java異常處理的目的在于通過(guò)使用少于目前數(shù)量的代碼來(lái)簡(jiǎn)化大型、可靠的程序的生成,并且通過(guò)這種方式可以使你更自信:你的應(yīng)用中沒(méi)有未處理的錯(cuò)誤。 12.1 概念 異...

    Vultr 評(píng)論0 收藏0
  • 異常機(jī)制詳解

    摘要:當(dāng)運(yùn)行時(shí)系統(tǒng)遍歷調(diào)用棧而未找到合適的異常處理器,則運(yùn)行時(shí)系統(tǒng)終止。不可查異常編譯器不要求強(qiáng)制處置的異常包括運(yùn)行時(shí)異常與其子類(lèi)和錯(cuò)誤。 目錄介紹 1.什么是異常 2.異常 2.1 異常的概述和分類(lèi)【了解】 2.2 JVM默認(rèn)是如何處理異常的【理解】 2.3 異常處理的兩種方式【理解】 2.4 try...catch的方式處理異?!菊莆铡?2.5 編譯期異常和運(yùn)行期異常的區(qū)別【理解】...

    wanghui 評(píng)論0 收藏0
  • Java中異常

    摘要:對(duì)異常的處理方法是打印異常的跟蹤棧信息并終止程序運(yùn)行。應(yīng)盡量對(duì)異常進(jìn)行適當(dāng)?shù)奶幚?,而不是?jiǎn)單的將異常跟蹤棧信息打印出來(lái)。 一、異常概述 開(kāi)發(fā)者都希望所有錯(cuò)誤都能在編譯階段被發(fā)現(xiàn),就是試圖在運(yùn)行程序之前排除所有錯(cuò)誤,但這是不現(xiàn)實(shí)的,余下問(wèn)題必須在運(yùn)行期間得到解決。 Java將異常分為兩種:CheckedException和RuntimeException。其中,CheckedExcept...

    wemall 評(píng)論0 收藏0
  • Java編程基礎(chǔ)20——異常&IO(File類(lèi))

    摘要:異常異常的概述和分類(lèi)異常的概述異常就是程序在運(yùn)行過(guò)程中出現(xiàn)的錯(cuò)誤。運(yùn)行時(shí)異常就是程序員所犯的錯(cuò)誤,需要回來(lái)修改代碼。獲取異常類(lèi)名和異常信息,返回字符串。如果路徑名不同,就是改名并剪切。刪除注意事項(xiàng)中的刪除不走回收站。 1_異常(異常的概述和分類(lèi)) A:異常的概述 異常就是Java程序在運(yùn)行過(guò)程中出現(xiàn)的錯(cuò)誤。 B:異常的分類(lèi) 通過(guò)API查看Throwable Error 服務(wù)...

    church 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<