PHP 錯誤處理(new Exception、new Error、trigger_error、error_log )

不記起來會忘記,雖然記起來會混亂,寫個筆記紀錄一下


本文將介紹如何觸發錯誤、錯誤級別介紹、處理錯誤、錯誤日誌的寫法。

觸發錯誤

使用 Exception 類別

這種方式用於例外處理,當你想捕捉並處理某些條件下的錯誤時,可以拋出一個例外。這通常用於邏輯錯誤或應用程式級別的錯誤。

try {
    throw new Exception("Division by zero.");
} catch (Exception $e) {
    echo "Caught exception: " . $e->getMessage();
}

使用 Error 類別

Error 類別是從 PHP 7 開始引入的,用於處理更底層的錯誤,例如語法錯誤或類型錯誤。這些錯誤通常表示程式碼中的嚴重問題,應該被捕捉並記錄。

try {
    throw new Error("Division by zero.");
} catch (Error $e) {
    echo "Caught error: " . $e->getMessage();
}

使用 trigger_error 函數

trigger_error 函數允許你生成一個用戶定義的錯誤。這對於在開發過程中發出警告或錯誤訊息非常有用。你可以指定錯誤等級,例如 E_USER_WARNING 或 E_USER_ERROR。

trigger_error("This is a user-generated warning.", E_USER_WARNING);
trigger_error("This is a user-generated error.", E_USER_ERROR);

範例對比

以下是一個綜合範例,展示了這三種錯誤發出的方式及其處理方法:

// 自訂錯誤處理函數
function customErrorHandler($errno, $errstr, $errfile, $errline) {
    error_log("Error: [$errno] $errstr - $errfile:$errline");
    echo "Handled error: $errstr<br>";
    return true;
}

// 設定自訂錯誤處理函數
set_error_handler("customErrorHandler");

// 使用 Exception
try {
    throw new Exception("This is an exception.");
} catch (Exception $e) {
    echo "Caught exception: " . $e->getMessage() . "<br>";
}

// 使用 Error
try {
    throw new Error("This is an error.");
} catch (Error $e) {
    echo "Caught error: " . $e->getMessage() . "<br>";
}

// 使用 trigger_error
trigger_error("This is a user-generated warning.", E_USER_WARNING);
trigger_error("This is a user-generated error.", E_USER_ERROR);

// 此行仍然會被執行
echo "hello world!";

這個範例中,Exception 和 Error 被捕捉並處理,而 trigger_error 生成的錯誤則由自訂錯誤處理函數處理。程式不會中止,並且會輸出所有錯誤訊息。

錯誤級別表

系統級別錯誤

錯誤級別中止程式引發者情境描述
E_ERROR系統致命的運行錯誤,例如無效的函數調用
E_WARNING系統運行時警告,例如包含不存在的文件
E_PARSE系統解析錯誤,例如語法錯誤
E_NOTICE系統運行時通知,例如使用未定義的變數
E_CORE_ERROR系統PHP 啟動時的致命錯誤
E_CORE_WARNING系統PHP 啟動時的警告
E_COMPILE_ERROR系統編譯時的致命錯誤
E_COMPILE_WARNING系統編譯時的警告
E_STRICT系統建議的代碼改進措施
E_RECOVERABLE_ERROR系統可捕捉的致命錯誤,例如類型錯誤
E_DEPRECATED系統運行時通知,不建議使用的代碼

用戶級別錯誤

錯誤級別中止程式引發者情境描述
E_USER_ERROR用戶 trigger_error()用戶生成的致命錯誤,例如自訂的致命錯誤
E_USER_WARNING用戶 trigger_error()用戶生成的警告,例如自訂的警告訊息
E_USER_NOTICE用戶 trigger_error()用戶生成的通知,例如自訂的通知訊息
E_USER_DEPRECATED用戶 trigger_error()用戶生成的過時警告,例如自訂的不建議使用的代碼警告

處理錯誤

以下介紹錯誤處裡的方法:
set_error_handler
set_exception_handler
register_shutdown_function

使用 set_error_handler 處理的錯誤

錯誤級別會中止程式引發者簡單描述情境
E_WARNING系統運行時警告,例如包含不存在的文件
E_NOTICE系統運行時通知,例如使用未定義的變數
E_USER_WARNING用戶 (trigger_error())用戶生成的警告
E_USER_NOTICE用戶 (trigger_error())用戶生成的通知
E_USER_ERROR用戶 (trigger_error())用戶生成的致命錯誤
E_USER_DEPRECATED用戶 (trigger_error())用戶生成的過時警告
E_DEPRECATED系統運行時通知,不建議使用的代碼
E_RECOVERABLE_ERROR系統可捕捉的致命錯誤,例如類型錯誤

使用 set_exception_handler 處理的例外

錯誤類型會中止程式引發者簡單描述情境
Exception用戶例如 throw new Exception
Error用戶例如 throw new Error

使用 register_shutdown_function 處理的錯誤

錯誤級別會中止程式引發者簡單描述情境
E_ERROR系統致命的運行錯誤,例如無效的函數調用
E_CORE_ERROR系統PHP 啟動時的致命錯誤
E_COMPILE_ERROR系統編譯時的致命錯誤
E_PARSE系統解析錯誤,例如語法錯誤

這些表格展示了不同的錯誤處理方法以及它們可以處理的錯誤類型,確保你可以有效地處理所有可能發生的錯誤和例外。

錯誤處裡範例

set_error_handler()

系統只會有一個有作用的 set_error_handler(),後面設置的 handler 會覆蓋前面設置 handler,無法刪除,如有套件設置了,可以用覆蓋的或 set_error_handler(null) 使 handler 失去作用

try-catch

捕獲到 Error or Exception 可統一進行錯誤處裡,當然也可以捕獲後步處理,或存於 error_log

// 自訂錯誤處理函數
function customErrorHandler($errno, $errstr, $errfile, $errline) {
    echo "Handled error: [$errno] $errstr - $errfile:$errline<br>";
    // 記錄錯誤到日誌文件
    error_log("Error: [$errno] $errstr - $errfile:$errline");
    return true; // 返回 true 以避免 PHP 預設的錯誤處理
}

// 設定自訂錯誤處理函數
set_error_handler("customErrorHandler");

// 捕獲和處理 Exception 和 Error 的自訂處理函數
function handleExceptionOrError($e) {
    $errno = ($e instanceof Error) ? E_USER_ERROR : E_USER_WARNING;
    customErrorHandler($errno, $e->getMessage(), $e->getFile(), $e->getLine());
}

// 捕獲和處理 Exception
try {
    throw new Exception(" Exception: massage.");
} catch (Exception $e) {
    // 呼叫 handleExceptionOrError 處理 Exception
    handleExceptionOrError($e);
}

// 捕獲和處理 Error
try {
    throw new Error(" Error: massage.");
} catch (Error $e) {
    // 呼叫 customErrorHandler 處理 Error
    customErrorHandler($errno, $e->getMessage(), $e->getFile(), $e->getLine());
}

輸出:

Handled error: [512] Exception: massage. - C:\...\system\modules\error\try-catch.php:21
Handled error: [8] Undefined variable: errno - C:\...\system\modules\error\try-catch.php:32
Handled error: [] Error: massage. - C:\...\system\modules\error\try-catch.php:29

錯誤日誌

錯誤日誌就像飛機的黑盒子,記錄著所有錯誤發生的詳細信息,讓我們能夠在錯誤發生後進行分析和診斷,從而提高應用程式的穩定性和可靠性。

以下是錯誤日誌寫法:

// 1. 將錯誤訊息寫入到 PHP 的系統日誌
error_log("Error occurred.");

// 2. 將錯誤訊息發送到指定的 email 地址
error_log("Error occurred.", 1, "admin@example.com");

// 3. 將錯誤訊息發送到 PHP 的測試工具連接
error_log("Error occurred.", 2);

// 4. 將錯誤訊息附加到指定的文件
error_log("Error occurred.", 3, "/path/to/your/error.log");

綜合錯誤處裡

// 自訂錯誤處理函數
function customErrorHandler($errno, $errstr, $errfile, $errline) {
    $errorMessage = "Error: [$errno] $errstr - $errfile:$errline\n";
    
    // 根據錯誤級別記錄到不同的日誌文件
    switch ($errno) {
        case E_USER_ERROR:
            error_log($errorMessage, 3, "/path/to/your/user_error.log");
            break;
        case E_USER_WARNING:
            error_log($errorMessage, 3, "/path/to/your/user_warning.log");
            break;
        case E_USER_NOTICE:
            error_log($errorMessage, 3, "/path/to/your/user_notice.log");
            break;
        default:
            error_log($errorMessage, 3, "/path/to/your/general_error.log");
            break;
    }
    
    echo "Handled error: $errstr<br>";
    return true;
}

// 自訂例外處理函數
function customExceptionHandler($exception) {
    $errorMessage = "Exception: " . $exception->getMessage() . "\n";
    
    // 根據例外類型記錄到不同的日誌文件
    if ($exception instanceof Error) {
        error_log($errorMessage, 3, "/path/to/your/error.log");
    } else {
        error_log($errorMessage, 3, "/path/to/your/exception.log");
    }
    
    echo "Handled exception: " . $exception->getMessage() . "<br>";
}

// 自訂關閉時的錯誤處理函數
function shutdownHandler() {
    $error = error_get_last();
    if ($error !== NULL) {
        $errorMessage = "Shutdown error: " . $error['message'] . "\n";
        error_log($errorMessage, 3, "/path/to/your/shutdown_error.log");
        echo "Handled shutdown error: " . $error['message'] . "<br>";
    }
}

// 設定自訂錯誤和例外處理函數
set_error_handler("customErrorHandler");
set_exception_handler("customExceptionHandler");
register_shutdown_function("shutdownHandler");

// 觸發例外和錯誤
try {
    throw new Exception("This is an exception.");
} catch (Exception $e) {
    customExceptionHandler($e);
}

try {
    throw new Error("This is an error.");
} catch (Error $e) {
    customExceptionHandler($e);
}

trigger_error("This is a user-generated notice.", E_USER_NOTICE);
trigger_error("This is a user-generated warning.", E_USER_WARNING);
trigger_error("This is a user-generated error.", E_USER_ERROR);

// 此行可能不會執行,因為 E_USER_ERROR 是致命錯誤
echo "hello world!";

錯誤日誌的記錄不僅有助於在開發過程中及早發現和修復問題,還能在生產環境中提供寶貴的錯誤追蹤信息。透過詳細的錯誤日誌記錄,我們可以了解錯誤發生的時間、錯誤類型、錯誤訊息以及錯誤發生的文件和行號,這些資訊讓我們快速修正非常重要。

如果文章對您很有幫助
請我喝杯咖啡吧

Bitcoin 比特幣錢包:

38ieWXhURt27br9XrDoCeo4eruzKyi8QKs



ann71727

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料