不記起來會忘記,雖然記起來會混亂,寫個筆記紀錄一下
本文將介紹如何觸發錯誤、錯誤級別介紹、處理錯誤、錯誤日誌的寫法。
觸發錯誤
使用 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!";
錯誤日誌的記錄不僅有助於在開發過程中及早發現和修復問題,還能在生產環境中提供寶貴的錯誤追蹤信息。透過詳細的錯誤日誌記錄,我們可以了解錯誤發生的時間、錯誤類型、錯誤訊息以及錯誤發生的文件和行號,這些資訊讓我們快速修正非常重要。