錯誤級別常數與位元遮罩
PHP 使用位元遮罩組合錯誤級別,常見常數:
| 常數 | 值 | 說明 |
| E_ERROR | 1 | 致命運行時錯誤,腳本終止 |
| E_WARNING | 2 | 運行時警告,腳本繼續 |
| E_PARSE | 4 | 編譯時語法解析錯誤 |
| E_NOTICE | 8 | 運行時提示 (如未定義變數),腳本繼續 |
| E_STRICT | 2048 | 編碼標準建議 (PHP 5.4 併入 E_ALL) |
| E_DEPRECATED | 8192 | 棄用功能警告 |
| E_ALL | 32767 | 所有錯誤 (含 E_STRICT 視版本) |
設定方式
1. php.ini (全域、永久)
; 開發環境
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
error_log = /var/log/php_errors.log
; 生產環境
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
2. 運行時動態設定 (入口檔/配置檔)
<?php
// 開發環境:報告所有錯誤
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
// 生產環境:隱藏提示,記錄日誌
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/logs/php_errors.log');
3. 依環境變數自動切換 (推薦)
<?php
// 環境變數: APP_ENV=development|production
$env = getenv('APP_ENV') ?: 'production';
if ($env === 'development') {
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
} else {
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT);
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/../logs/php_errors.log');
}
// 自定義錯誤處理器 (可選,統一格式、發送告警)
set_error_handler(function ($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) return false; // 未啟用的級別忽略
$msg = "[$severity] $message in $file:$line";
error_log($msg);
if (ini_get('display_errors')) echo "$msg
";
return true; // 不執行內部處理器
});
生產環境為什麼要關閉 display_errors?
- 資安:錯誤訊息常洩露絕對路徑、資料庫結構、程式碼片段、變數值,助攻攻擊者偵察。
- 使用者體驗:紅字警告破壞版面,降低信任度。
- 合規:GDPR、PCI-DSS 等要求不向最終用戶暴露系統細節。
進階:錯誤轉例外 (PHP 7+)
set_error_handler(function ($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) return;
throw new ErrorException($message, 0, $severity, $file, $line);
});
// 現在可用 try-catch 捕獲 E_WARNING、E_NOTICE 等
try {
$x = $undefinedVar; // E_NOTICE → ErrorException
} catch (ErrorException $e) {
// 統一處理
}
常見誤區
error_reporting(0) 會屏蔽**所有**錯誤,連致命錯誤都不記錄,除非極特殊場景否則**禁用**。
- 以 `@` 抑制錯誤 (`@$file = fopen(...)`) 會隱藏關鍵訊息,除非明確預期失敗並檢查回傳值,否則**避免使用**。
- 僅設定 `display_errors=Off` 而不設 `log_errors=On`,導致錯誤「石沉大海」,排查極難。
總結清單
| 環境 | error_reporting | display_errors | log_errors | error_log | 備註 |
| 開發 | E_ALL | On | On | 檔案/標準錯誤 | 即時見錯誤 |
| 測試/預發 | E_ALL & ~E_NOTICE | Off | On | 檔案 | 接近生產 |
| 生產 | E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT | Off | On | 集中日誌系統 (ELK/Sentry) | 零容忍洩露 |