本文目录导读:

在PHP项目中实现日志记录,通常有以下几种主流方案,从简单到专业:
使用 PHP 原生函数(最简单)
<?php
// 写入系统日志
error_log("用户登录失败:用户名不存在", 0);
// 写入自定义文件
error_log("错误信息", 3, "/var/log/myapp.log");
?>
优点:零依赖,开箱即用 缺点:功能单一,不支持分级、格式化
自定义日志函数(小项目)
<?php
class Logger {
private static $logFile;
public static function init($file = 'app.log') {
self::$logFile = __DIR__ . '/logs/' . $file;
if (!file_exists(dirname(self::$logFile))) {
mkdir(dirname(self::$logFile), 0755, true);
}
}
public static function write($level, $message, $context = []) {
$timestamp = date('Y-m-d H:i:s');
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$caller = $trace[1] ?? null;
$file = $caller['file'] ?? 'unknown';
$line = $caller['line'] ?? 0;
$contextStr = !empty($context) ? ' ' . json_encode($context) : '';
$logMessage = "[{$timestamp}] [{$level}] [{$file}:{$line}] {$message}{$contextStr}" . PHP_EOL;
error_log($logMessage, 3, self::$logFile);
}
public static function info($message, $context = []) {
self::write('INFO', $message, $context);
}
public static function error($message, $context = []) {
self::write('ERROR', $message, $context);
}
public static function debug($message, $context = []) {
if (defined('APP_DEBUG') && APP_DEBUG) {
self::write('DEBUG', $message, $context);
}
}
}
// 使用
Logger::init('app.log');
Logger::info('用户登录成功', ['user_id' => 123, 'ip' => '192.168.1.1']);
Logger::error('数据库连接失败', ['db' => 'main', 'error' => 'timeout']);
?>
使用 Monolog 库(推荐方案)
Monolog 是 PHP 最流行的日志库,几乎所有现代框架都在使用。
安装
composer require monolog/monolog
基本使用
<?php
require 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\LineFormatter;
use Monolog\Processor\IntrospectionProcessor;
use Monolog\Processor\WebProcessor;
// 创建日志频道
$log = new Logger('app');
// 1. 简单文件日志
$log->pushHandler(new StreamHandler(__DIR__.'/logs/app.log', Logger::DEBUG));
// 2. 按天轮转(推荐)
$handler = new RotatingFileHandler(__DIR__.'/logs/app.log', 30, Logger::DEBUG);
$log->pushHandler($handler);
// 3. 自定义格式
$dateFormat = "Y-m-d H:i:s";
$output = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
$formatter = new LineFormatter($output, $dateFormat);
$handler->setFormatter($formatter);
// 4. 添加上下文信息
$log->pushProcessor(new IntrospectionProcessor());
$log->pushProcessor(new WebProcessor());
// 使用
$log->info('用户登录', ['user_id' => 123]);
$log->error('数据库错误', ['exception' => $e->getMessage()]);
?>
进阶配置 - 多通道日志
<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SlackWebhookHandler;
use Monolog\Handler\SwiftMailerHandler;
// 创建多通道日志
$logger = new Logger('production');
// INFO 及以上记录到文件
$logger->pushHandler(new StreamHandler(
__DIR__.'/logs/info.log',
Logger::INFO
));
// ERROR 及以上发送到 Slack
$logger->pushHandler(new SlackWebhookHandler(
'https://hooks.slack.com/services/xxx',
'#php-errors',
'PHP Bot',
true, // use attachment
'danger',// icon emoji
true, // use short attachment
false, // include context
Logger::ERROR
));
// CRITICAL 发送邮件
$logger->pushHandler(new SwiftMailerHandler(
$mailer,
$message,
Logger::CRITICAL
));
// 使用
$logger->error('支付失败', ['order_id' => 12345]);
$logger->critical('服务器磁盘已满', ['disk_usage' => '99%']);
?>
使用框架内置日志
Laravel
// config/logging.php 配置
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'slack'],
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'info',
'days' => 14,
],
],
// 使用
use Illuminate\Support\Facades\Log;
Log::info('用户登录', ['user_id' => $id]);
Log::error('数据库查询失败', ['sql' => $query, 'error' => $e->getMessage()]);
ThinkPHP
// config/log.php 配置
return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
'path' => app()->getRuntimePath() . 'logs',
'level' => ['info', 'error', 'warning'],
'single' => false,
'file_size' => 2097152, // 2M
'max_files' => 30,
],
],
];
// 使用
use think\facade\Log;
Log::info('用户登录', ['user_id' => $id]);
Log::error('数据库查询失败', ['sql' => $query]);
最佳实践建议
日志级别规范
DEBUG: 调试信息(开发环境) INFO: 一般信息(用户操作) NOTICE: 正常但重要的事件 WARNING: 警告(潜在问题) ERROR: 错误(不影响系统运行) CRITICAL:严重错误(影响系统运行) ALERT: 需要立即处理 EMERGENCY:系统不可用
规范
// 好的日志
$log->info('用户登录成功', [
'user_id' => 123,
'ip' => '192.168.1.1',
'user_agent' => 'Chrome/120.0',
'duration' => 0.15
]);
// 避免这种
$log->info('登录成功'); // 缺少有用信息
环境配置
// 根据环境设置不同级别
if (getenv('APP_ENV') === 'production') {
$handler->setLevel(Logger::WARNING); // 生产只记录警告及以上
} else {
$handler->setLevel(Logger::DEBUG); // 开发环境记录所有
}
安全注意事项
- 不要记录敏感信息:密码、身份证、信用卡号等
- 日志文件权限:设置为 644,避免直接访问
- 日志目录隔离:放在 web 根目录之外
- 定期清理:设置日志保留天数
推荐方案
对于大多数 PHP 项目,推荐:
- 小项目:自定义 Logger 类 + 文件日志
- 中大型项目:Monolog + 文件 + 错误监控
- 框架项目:使用框架提供的日志功能
选择方案时考虑项目规模、维护成本、是否需要远程告警等因素。