PHP日志系统需分层落地:先通过php.ini开启log_errors、指定error_log路径并关闭display_errors;再用error_log()、set_error_handler()和set_exception_handler()补充上下文;进阶用Monolog实现结构化多通道输出;最后用grep/awk等命令快速分析日志。

PHP网站搭建日志系统,关键不在堆功能,而在于分层落地:基础错误捕获要稳、日志内容要可读、存储方式要可控、分析路径要直接。生产环境不记录错误,等于闭着眼开车。
用php.ini统一开启并约束错误日志
这是最基础也最关键的一步。修改服务器全局配置,确保所有PHP脚本的未捕获错误自动落盘:
- 设 log_errors = On,启用日志写入
- 指定 error_log = /var/log/php_errors.log(路径需绝对,目录须存在)
- 关闭前端暴露:display_errors = Off(生产环境严禁开启)
- 按需设置错误级别,例如开发期用 error_reporting = E_ALL,线上常用 E_ALL & ~E_NOTICE & ~E_DEPRECATED
- 改完后重启 PHP-FPM 或 Web 服务(如
sudo systemctl restart php8.2-fpm)
用error_log()或自定义处理器补充上下文
php.ini只能记“发生了什么”,但查问题常需要“谁在什么时候、什么页面、带什么参数触发的”。这时需主动增强:
- 在入口文件或公共函数中调用
error_log("用户登录失败 | UID:{$uid} | IP:{$_SERVER['REMOTE_ADDR']}", 3, "/var/log/app_access.log") - 用 set_error_handler() 捕获非致命错误(如 Warning),拼接
$_SERVER['REQUEST_URI']和$_POST片段(注意脱敏) - 用 set_exception_handler() 统一处理未捕获异常,记录完整堆栈和请求ID
- 避免在处理器里直接 echo 或 exit,保持原有错误流程继续执行
引入Monolog实现结构化与多通道输出
当项目变大、团队协作增多,纯文本日志难检索、难归档、难报警。Monolog 提供标准化支持:
立即学习“PHP免费学习笔记(深入)”;
- 通过 Composer 安装:
composer require monolog/monolog - 创建 Logger 实例,添加
RotatingFileHandler(按天轮转)、StreamHandler(写文件)、SlackHandler(告警) - 按场景调用:
$logger->info('订单创建成功', ['order_id' => $id, 'amount' => $amt]),字段自动 JSON 化 - 框架如 Laravel 已内置 Monolog,只需修改
config/logging.php中的 channel 配置即可生效
用命令行或工具快速定位高频错误
日志写了不用,等于没写。日常排查不必打开大屏平台,终端几条命令就能见效:
- 查最近致命错误:
grep "PHP Fatal error\|PHP Parse error" /var/log/php_errors.log | tail -20 - 统计每小时 500 错误次数:
awk '{print substr($1,2,13)}' /var/log/php_errors.log | sort | uniq -c - 提取所有 SQL 相关警告:
grep -i "mysql\|pdo\|query" /var/log/php_errors.log - 配合
logrotate自动归档(配置/etc/logrotate.d/php),保留 30 天日志,防磁盘打满



















