error_log()是最轻量的日志方式,但需用绝对路径、检查目录写权限、避免相对路径;建议封装加时间戳和级别,或用file_put_contents()配合file_append|lock_ex实现原子写入;小项目无需monolog。

PHP用error_log()写日志最轻量,但要注意路径和权限
直接调用error_log()是最省事的方式,不用装包、不依赖扩展。它默认把内容写进 Web 服务器的错误日志(比如 Apache 的 error.log),但你也可以指定文件路径:
error_log("用户登录失败:ID=123", 3, "/var/log/myapp/access.log");
其中第二个参数 3 表示“写入文件”,第三个参数是绝对路径。注意:PHP 进程必须对目标目录有写权限,否则静默失败——不会报错,但日志根本不会出现。常见坑是用了相对路径(比如 "logs/app.log"),结果写到 Web 根目录或临时目录去了,根本找不到。
- 确保路径存在且可写:
is_writable(dirname($path))最好先检查 - 生产环境别用
2(发送到 syslog),行为因系统而异,不易排查 - 如果日志量大,
error_log()没缓冲、没轮转,容易撑爆磁盘
自己封装一个log()函数,加时间戳和级别更实用
原生error_log()不带时间、不区分级别,线上查问题时效率低。简单封装一层就能解决:
function log($msg, $level = 'INFO') {<br> $time = date('Y-m-d H:i:s');<br> $line = "[$time][$level] $msg" . PHP_EOL;<br> error_log($line, 3, '/var/log/myapp/app.log');<br>}
这样调用就清晰多了:log("订单创建成功", "INFO") 或 log("数据库连接超时", "ERROR")。关键点在于:一定要加 PHP_EOL,否则所有日志会挤在一行;级别字符串建议全大写,方便 grep 筛选;如果项目有多个模块,可以在 $msg 前加前缀,比如 "[auth] 用户密码错误"。
用file_put_contents()追加写入,比error_log()更可控
当需要原子写入、或想控制文件打开模式时,file_put_contents() 更合适:
file_put_contents(<br> '/var/log/myapp/app.log',<br> "[" . date('c') . "] ERROR: DB query failed\n",<br> FILE_APPEND | LOCK_EX<br>);
FILE_APPEND 确保不覆盖,LOCK_EX 防止并发写入错乱(尤其在 CLI 脚本或高并发请求中)。注意:file_put_contents() 返回写入字节数,失败返回 false,可以加判断;但它不会自动创建父目录,/var/log/myapp/ 必须提前存在。
- 不要用
FILE_USE_INCLUDE_PATH,跟日志无关还可能引入安全风险 - 避免在循环里高频调用——每次都是系统调用,IO 开销明显
- 如果日志要按天分割,得自己拼日期路径,比如
"/var/log/app_".date('Y_m_d').".log"
别急着上 Monolog,小项目真没必要
Monolog 功能强,支持 Handler、Formatter、Processor,但引入后 vendor 目录多出几百个文件,autoload 加载变慢,部署也更重。除非你明确需要:日志推送到 Slack、自动切分归档、结构化 JSON 输出给 ELK、或需对接 PSR-3 标准——否则纯 PHP 后台脚本,手写百来行封装已够用。
真正容易被忽略的是日志敏感信息:密码、token、身份证号,千万别直接log($user_input)。哪怕只是调试,也要做脱敏,比如 substr($id, 0, 4) . '****'。还有就是错误日志级别混用——把 WARNING 当 INFO 用,时间一长告警就失去意义。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











