php7的錯誤與例外處理

2020-08-12 14:01:01

錯誤

錯誤是寫程式中不可避免的,如何去發現定位錯誤及改正更是一門學問。今天和大家聊聊之後的錯誤與異常。

錯誤的分類

一般錯誤分爲語法錯誤、執行時錯誤、邏輯錯誤。語法以及執行時錯誤很容易去排查,但邏輯錯誤就不是那麼簡單的了。鄙人在判斷的時候也有多次將比較運算==寫成了賦值運算=,像我這種就很難去發現。一般隨着經驗的豐富(踩坑踩多了),會越來越容易來找到邏輯錯誤。

控制錯誤的輸出

一般建議開發階段開啓錯誤輸出方便及時發現錯誤,上線階段爲了安全性及美觀建議關閉錯誤輸出。

php提供了一個參數display_errors用於控制錯誤向瀏覽器、cli的輸出。有兩種方式可以來修改它,通過修改php.ini檔案或使用ini_set函數來設定。下面 下麪展示使用ini_set來設定遮蔽錯誤輸出的程式碼。

<?php
ini_set('display_errors', 0);

echo $a;
echo 0;
date();
echo 1;

該程式會正常輸出01,但不會輸出錯誤資訊。

錯誤報告級別

一般分爲4大類

  • parse語法錯誤

  • error致命錯誤

  • warning警告級別錯誤

  • notice注意級別錯誤

在php.ini組態檔中,有選項error_reporting,該選項用來控制輸出何種級別的錯誤。常見的有E_ALL、E_WARNING、E_NOTICE。

可以通過函數error_reporting()來動態控制錯誤級別的輸出。

# 輸出所有級別錯誤
error_reporting(E_ALL);
# 輸出所有級別除了E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
# 輸出所有級別除了E_NOTICE和E_WARNING
error_reporting(E_ALL & ~(E_NOTICE | E_WARNING));

display_errors與error_reporting的區別

display_errors是用來控制錯誤是否輸出,而error_reporting是用來控制輸出何種級別的錯誤。通常他們會搭配使用

ini_set('display_errors', 0); // 關閉錯誤輸出
error_reporting(E_ALL);  // 輸出所有級別的錯誤資訊

上面的設定一般是上線階段,遮蔽所有的錯誤輸出,但是記錄錯誤到php的錯誤日誌裡。錯誤日誌的路徑是由選項error_log 決定的。

如果設定error_reporting爲0值,則不輸出錯誤也不記錄錯誤日誌。

錯誤對於程式的影響

當程式有語法錯誤時,程式是不會執行的。當有error級別的錯誤時,程式就會停止向下執行。notice、及warning級別錯誤時不會影響程式的向下執行的。

error_reporting(E_ALL);  // 輸出所有級別的錯誤資訊

echo $a;
echo 0;
date();
echo 1;
new a;
echo 2;

該程式會輸出0和1,但不會輸出2。

使用者自定義錯誤

trigger_error()函數可以生產一個使用者級別的錯誤。錯誤級別有E_USER_ERROR 、E_USER_WARNING、E_USER_NOTICE 等

<?php

trigger_error('這是notice級別錯誤', E_USER_NOTICE);
trigger_error('warning錯誤', E_USER_WARNING);
trigger_error('deprecated', E_USER_DEPRECATED);
trigger_error('error錯誤', E_USER_ERROR);

自定義錯誤處理

set_error_handler — 設定使用者自定義的錯誤處理常式,該函數原型如下:

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

該函數首個參數是一個回撥函數,原型如下:

handler ( int $errno , string $errstr [, string $errfile [, int $errline [, array $errcontext ]]] ) : bool
  • error 錯誤級別

  • errstr 錯誤資訊

  • errfile 發送錯誤的檔案

  • errline 錯誤出現的行號

以下級別的錯誤不能由使用者定義的函數來處理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在呼叫 set_error_handler() 函數所在檔案中產生的大多數 E_STRICT。

<?php
 
define('DEBUG', false);
 
set_error_handler('error_handler');
 
if (DEBUG) {
    ini_set('display_errors', 'On');
} else {
    ini_set('display_errors', 'Off');
}
 
function error_handler($errLevel, $errInfo, $errFile, $errLine)
{
    echo "ErrorLevel:$errLevel: $errInfo In $errFile ON $errLine" . PHP_EOL;
}
 
echo $a;

異常

異常和錯誤時有區別的,錯誤一般是指我們能控制的問題,比如變數名寫錯了,或者判斷條件寫的不錯,導致死回圈。而異常通常指那些難以控制的、意料外的錯誤,比如mysql連線不上,檔案控制代碼開啓失敗等情況。

php的異常也是經典的try catch finally,但和一般的例外處理不一樣的是,絕大部分的異常需要自行拋出。拋出異常使用throw關鍵字完成。php也支援捕獲多個異常。

<?php

class MyError extends Exception
{
    public function printErr ()
    {
        echo '出錯啦'.PHP_EOL;
    }
}

class YourError extends Exception
{
    public function printErr ()
    {
        echo 'errors'.PHP_EOL;
    }
}

try {
    if (mt_rand(0,1)) {
        throw new MyError('錯誤');
    } else {
        throw new YourError('錯誤');
    }


} catch (MyError $e) {
    $e->printErr();
} catch (YourError $e) {
    $e->printErr();
} finally {
    echo '不管有沒有異常,我都會被執行'.PHP_EOL;
}

php的異常如果沒有捕獲,則會報Fatal Error錯誤,程式不會繼續向下執行。

PHP 7 錯誤處理

PHP 7 改變了大多數錯誤的報告方式。不同於傳統(PHP 5)的錯誤報告機制 機製,現在大多數錯誤被作爲 Error 異常拋出。 Error 和 Exception 都實現了 Throwable 介面

例外處理

設定預設的例外處理程式,有try/catch捕獲的話這個異常函數就不會執行,反之就會執行例外處理函數,而且執行的話,指令碼將不會繼續執行。

php使用set_exception_handler來設定使用者自定義的例外處理函數 ,函數原型如下:

set_exception_handler ( callable $exception_handler ) : callable

回撥函數的原型如下:

handler ( Throwable $ex ) : void

下面 下麪,我們來寫一個例外處理函數

<?php

class MyError extends Exception
{
    public function printErr ()
    {
        echo '出錯啦'.PHP_EOL;
    }
}

class YourError extends Exception
{
    public function printErr ()
    {
        echo 'errors'.PHP_EOL;
    }
}

try {
    if (mt_rand(0,1)) {
        throw new MyError('錯誤');
    } else {
        throw new YourError('錯誤');
    }


} catch (MyError $e) {
    $e->printErr();
} catch (YourError $e) {
    $e->printErr();
} finally {
    echo '不管有沒有異常,我都會被執行'.PHP_EOL;
}

統一處理錯誤與異常

學完了錯誤與異常,知道如何去使用自定義錯誤處理和例外處理,現在我們就可以統一處理錯誤與異常了。

<?php
 
class Errors
{
    // 處理非致命錯誤
    static function errorHandle($errLevel, $errInfo, $errFile, $errLine)
    {
        echo '錯誤:'.PHP_EOL;
        print_r(['file' => $errFile, 'level' => $errLevel, 'line' => $errLine, 'info' => $errInfo]);
    }
 
    // 處理致命錯誤及異常
    static function exceptionHandle(Throwable $ex)
    {
        echo '異常:'.PHP_EOL;
        print_r(['file' => $ex->getFile(), 'level' => $ex->getCode(), 'line' => $ex->getLine(), 'info' => $ex->getMessage()]);
    }
}
 
set_error_handler(['Errors', 'errorHandle']);
set_exception_handler(['Errors', 'exceptionHandle']);

以上就是php7的錯誤與例外處理的詳細內容,更多請關注php中文網其它相關文章!