PHP 錯誤回顯雖利於開發調試,但生產環境若開啟會洩露路徑、資料庫結構、變數值等敏感資訊,嚴重威脅安全。本文說明如何透過 php.ini 徹底關閉錯誤顯示、正確配置錯誤日誌,並解決 display_errors = Off 失效的常見原因。
; php.ini 生產環境推薦配置
display_errors = Off ; 關閉頁面顯示
display_startup_errors = Off ; 關閉啟動階段錯誤顯示
error_reporting = E_ALL ; 記錄所有級別錯誤(含 Deprecated、Strict)
log_errors = On ; 開啟日誌記錄
error_log = /var/log/php/error.log ; 指定日誌檔案路徑(需可寫權限)
替代方案(僅記錄非 Notice):
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT
官方文件明確指出:當 log_errors = On 時,必須正確設定 error_log 路徑且該檔案可寫。否則 PHP 會忽略 display_errors = Off,強制將錯誤輸出到頁面(作為 fallback)。
log_errors = Off,問題徹底解決。<?php
// 入口檔案最頂端
ini_set('display_errors', '0');
ini_set('display_startup_errors', '0');
error_reporting(E_ALL);
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/../logs/php_error.log');
// 自定義錯誤處理器(可選,整合 Monolog、Sentry 等)
set_error_handler(function ($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) return false;
error_log(sprintf('[%s] %s in %s:%d', date('c'), $message, $file, $line));
return true; // 不執行內建處理器
});
set_exception_handler(function ($e) {
error_log(sprintf('[EXCEPTION] %s in %s:%d', $e->getMessage(), $e->getFile(), $e->getLine()));
// 生產環境返回友好錯誤頁
http_response_code(500);
include __DIR__ . '/views/500.php';
exit;
});
| 配置項 | 開發環境 | 生產環境 |
|---|---|---|
| display_errors | On | Off |
| error_reporting | E_ALL | E_ALL |
| log_errors | On | On |
| error_log | /tmp/php_dev.log | /var/log/php/error.log |
| xdebug.mode | develop,debug | off |
建議:使用 php.ini-development / php.ini-production 模板,或透過 Docker 環境變數注入,實現零代碼差異部署。
<?php
// test_error.php
trigger_error('測試錯誤訊息', E_USER_WARNING);
// 訪問此頁:生產環境應無輸出,日誌檔案應有記錄
生產環境必須 關閉 display_errors、開啟 log_errors、正確設定 error_log。若 display_errors = Off 不生效,請優先檢查 log_errors 與 error_log 配置。配合自定義錯誤/異常處理器接入日誌平台(ELK、Sentry、Loki),即可構建「用戶無感、開發可追、安全合規」的錯誤處理體系。