在 PHP 專案開發中,完善的日誌機制是除錯、監控與審計的基石。本文提供一個可直接用於生產環境的日誌寫入函數,支援自動建立目錄、日期分檔、請求上下文記錄等實用功能。
<?php
/**
* 寫入錯誤/除錯日誌
* @param string $content 日誌內容
* @param string $logDir 日誌根目錄 (預設 /logs)
*/
function logError($content, $logDir = '/logs') {
// 依日期分檔:debuglog_20240115.txt
$logFile = $logDir . '/debuglog_' . date('Ymd') . '.txt';
// 確保目錄存在,遞迴建立並設定權限
$dir = dirname($logFile);
if (!is_dir($dir)) {
@mkdir($dir, 0755, true);
}
// 組裝日誌行:[時間] - [請求URI] : 內容
$logLine = sprintf(
"[%s] -[%s] : %s\n",
date('Y-m-d H:i:s'),
$_SERVER['REQUEST_URI'] ?? 'CLI',
$content
);
// 追加寫入 (3 表示寫入檔案)
error_log($logLine, 3, $logFile);
}
?>
Web 伺服器進程需具備日誌目錄的寫入權限,典型部署命令:
# 假設 Apache 執行使用者為 www:www
chown -R www:www /var/www/html/logs
chmod 755 /var/www/html/logs
若使用 PHP-FPM,請將擁有者改為對應的 pool 使用者(如 www-data)。可用 ls -l 確認目前權限。
function logStructured(array $data) {
$data['timestamp'] = date('c');
$data['request_id'] = $_SERVER['HTTP_X_REQUEST_ID'] ?? uniqid();
logError(json_encode($data, JSON_UNESCAPED_UNICODE));
}
function logMessage($level, $message, $context = []) {
$levels = ['debug', 'info', 'warning', 'error', 'critical'];
if (!in_array($level, $levels)) return;
$logFile = "/logs/{$level}_" . date('Ymd') . '.log';
$entry = sprintf(
"[%s] %s: %s %s\n",
date('Y-m-d H:i:s'),
strtoupper($level),
$message,
$context ? json_encode($context) : ''
);
error_log($entry, 3, $logFile);
}
syslog() 或專用日誌服務 (Monolog + Redis/Elasticsearch)。logrotate 定期壓縮清理舊日誌,避免磁碟耗盡。| 問題 | 原因 | 解決方案 |
|---|---|---|
| 日誌不寫入 | 目錄權限不足 | 檢查 Web 使用者對目錄的寫入權限 |
| 亂碼 | 編碼不一致 | 確保 PHP 檔案為 UTF-8 無 BOM,資料庫連線設定 charset=utf8mb4 |
| 效能下降 | 頻繁 I/O | 改用緩衝/非同步日誌庫 |
建立標準化的日誌機制,能大幅提升系統可觀測性,是專業 PHP 開發的必備基本功。