PHP 提供 trigger_error() 讓開發者在業務邏輯中主動拋出錯誤,配合錯誤級別常數實現分級處理。同時 @ 抑制符可暫時屏蔽錯誤輸出。本文系統整理用法、級別對照表與最佳實務。
<?php
// 抑制單一表達式的錯誤輸出
$content = @file_get_contents('not_exist.txt'); // 不會輸出 Warning
// 配合自訂錯誤處理器
set_error_handler(function($severity, $message, $file, $line) {
if (error_reporting() === 0) return false; // @ 生效時 error_reporting() 為 0
// 正常處理邏輯
});
?>
注意:@ 會降低效能,且隱藏真實問題,**生產代碼嚴禁濫用**,僅限極少數明確預期失敗且已處理的場景 (如 @mkdir() 已存在目錄)。
<?php
function divide($a, $b) {
if ($b == 0) {
// 拋出使用者警告,不中斷腳本
trigger_error('除數不能為零', E_USER_WARNING);
return false;
}
return $a / $b;
}
echo divide(10, 2); // 5
echo divide(10, 0); // 輸出 Warning: 除數不能為零 in ... on line X
echo "腳本繼續執行"; // 仍會執行
?>
| 常數 | 值 | 描述 | 可由 trigger_error 拋出 |
|---|---|---|---|
E_USER_ERROR | 256 | 使用者致命錯誤,**腳本終止** | 是 |
E_USER_WARNING | 512 | 使用者警告,腳本繼續 | 是 |
E_USER_NOTICE | 1024 | 使用者通知,腳本繼續 | 是 |
E_USER_DEPRECATED | 16384 | 使用者棄用警告 (PHP 5.3+) | 是 |
E_ERROR | 1 | 核心致命錯誤 | 否 |
E_WARNING | 2 | 核心警告 | 否 |
E_NOTICE | 8 | 核心通知 | 否 |
E_DEPRECATED | 8192 | 核心棄用警告 | 否 |
E_RECOVERABLE_ERROR | 4096 | 可捕獲致命錯誤 (型別提示失敗) | 否 |
<?php
function processOrder($orderId, $amount) {
// 業務規則驗證
if (!is_numeric($orderId)) {
trigger_error("訂單 ID 必須為數字: $orderId", E_USER_ERROR); // 致命,停止
}
if ($amount <= 0) {
trigger_error("金額必須大於零: $amount", E_USER_WARNING); // 警告,記錄但繼續
}
if ($amount > 10000) {
trigger_error("大額訂單需人工審核: $amount", E_USER_NOTICE); // 通知,僅記錄
}
// 正常處理邏輯
return ['status' => 'ok', 'order_id' => $orderId];
}
// 設定錯誤報告級別 (開發環境建議全部開啟)
error_reporting(E_ALL);
// 測試
var_dump(processOrder('A123', 100)); // E_USER_ERROR -> Fatal error, 腳本停止
var_dump(processOrder(1001, -50)); // E_USER_WARNING -> Warning, 繼續執行
var_dump(processOrder(1002, 50000)); // E_USER_NOTICE -> Notice, 繼續執行
?>
<?php
set_error_handler(function($severity, $message, $file, $line) {
// 忽略 @ 抑制的錯誤
if (error_reporting() === 0) return false;
$levels = [
E_ERROR => 'ERROR', E_WARNING => 'WARNING', E_NOTICE => 'NOTICE',
E_USER_ERROR => 'USER_ERROR', E_USER_WARNING => 'USER_WARNING',
E_USER_NOTICE => 'USER_NOTICE', E_DEPRECATED => 'DEPRECATED',
E_USER_DEPRECATED => 'USER_DEPRECATED',
];
$level = $levels[$severity] ?? 'UNKNOWN';
// 寫入日誌檔案
$log = "[$level] $message in $file:$line\n";
file_put_contents(__DIR__ . '/error.log', $log, FILE_APPEND);
// 開發環境顯示詳細錯誤
if (ini_get('display_errors')) {
echo "[$level] $message in $file line $line";
}
// 致命錯誤不返回 true (讓 PHP 內建處理終止腳本)
if ($severity & (E_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR)) {
return false;
}
return true; // 表示已處理,不再由內建處理器處理
});
// 註冊致命錯誤捕獲 (register_shutdown_function)
register_shutdown_function(function() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR])) {
// 記錄致命錯誤
file_put_contents(__DIR__ . '/fatal.log', json_encode($error) . "\n", FILE_APPEND);
}
});
?>
E_USER_ERROR;業務邏輯異常但可降級 → E_USER_WARNING;資訊性提醒 → E_USER_NOTICEdisplay_errors=On, error_reporting=E_ALL;生產 display_errors=Off, log_errors=On, error_reporting=E_ALL & ~E_NOTICEfile_exists() 再 file_get_contents())Exception,錯誤處理器可轉換為 ErrorException 統一捕獲善用 trigger_error() 與分級錯誤機制,能建構可觀測、可維運的健壯 PHP 應用。