3、错误报告配置:php.ini中的error_reporting、display_errors、log_errors配置项
聊到PHP错误处理,绕不开的就是php.ini里的那三个老伙计。说实话,我见过太多项目上线后还开着错误显示,结果用户直接看到了数据库密码——那场面,真叫一个尴尬。
今天咱们就把这三个配置项掰开揉碎了讲清楚。你想想看,搞懂了它们,就等于掌握了PHP错误报告的开关和阀门。
3.1 error_reporting:你究竟想看哪些错误?
这个配置项说白了就是过滤器。它决定了哪些级别的错误会被PHP报告出来。我个人习惯把它理解成一个「权限清单」——只有清单上的错误类型,才有资格被处理。
核心概念:error_reporting 设置的是「错误级别」,而不是「是否显示」。它只负责筛选,不负责输出。
常见的错误级别常量如下:
| 常量 | 值 | 说明 |
|---|---|---|
| E_ALL | 32767 | 所有错误和警告(除E_STRICT在PHP 5.4.0前) |
| E_ERROR | 1 | 致命运行时错误,脚本终止 |
| E_WARNING | 2 | 运行时警告,脚本继续执行 |
| E_PARSE | 4 | 编译时语法解析错误 |
| E_NOTICE | 8 | 运行时通知,可能是代码小问题 |
| E_STRICT | 2048 | PHP建议的代码修改,确保互操作性 |
| E_DEPRECATED | 8192 | 运行时已弃用功能的警告 |
我在项目中遇到过一种情况:开发环境用E_ALL,结果被一堆NOTICE刷屏。其实很多NOTICE只是变量未定义,不影响运行。但说实话,上线前最好还是把这些小问题修掉,不然哪天突然变成E_WARNING就麻烦了。
我的建议:
- 开发环境:
error_reporting = E_ALL—— 别放过任何细节 - 测试环境:
error_reporting = E_ALL & ~E_DEPRECATED—— 忽略弃用警告,专注逻辑问题 - 生产环境:
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT—— 或者干脆E_ALL & ~E_NOTICE & ~E_DEPRECATED
你可能会问:为什么生产环境不直接用E_ALL?嗯,这里要注意——生产环境暴露任何错误信息都是安全隐患。而且有些第三方库会触发DEPRECATED警告,你总不能让用户看到「这个函数以后不能用了」这种提示吧?
3.2 display_errors:错误要不要给用户看?
这个配置项就简单了——它决定错误信息是否直接输出到浏览器。说白了就是「要不要让用户看到你的代码出了什么幺蛾子」。
取值只有两个:
- On:显示错误(开发环境用)
- Off:不显示错误(生产环境必须关)
我曾经踩过的坑:
有一次帮客户排查线上问题,发现display_errors是On。结果用户访问时,直接看到了数据库连接失败的堆栈信息——里面赫然写着数据库IP、用户名和密码。嗯,从那以后我每次上线前都会检查这个配置。
还有一个细节:display_errors 受 error_reporting 影响。就算你开了 display_errors = On,如果 error_reporting 设置为 0,那也不会显示任何错误。这两个配置是「与」的关系——两个条件都得满足,错误才会显示出来。
我个人习惯在开发环境这么配:
; php.ini 开发环境配置
error_reporting = E_ALL
display_errors = On
display_startup_errors = On ; 这个也建议打开,能看到PHP启动阶段的错误
生产环境则必须这样:
; php.ini 生产环境配置
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
display_errors = Off
display_startup_errors = Off
3.3 log_errors:把错误记下来,别让它跑了
display_errors关了,错误去哪了?答案就是日志。log_errors 配置项决定是否将错误写入日志文件。
这个配置我建议永远设为On。你想想看,生产环境关了错误显示,如果连日志都不记,那出了问题你连查都没地方查。
配套的还有两个配置:
- error_log:指定日志文件路径。如果不设置,默认会写到Web服务器的错误日志里(比如Apache的error_log)。
- log_errors_max_len:每条错误日志的最大长度,默认1024字节。我一般设成0(不限长度),因为截断的日志有时候反而让人摸不着头脑。
最佳实践组合:
; 生产环境标准配置
log_errors = On
error_log = /var/log/php_errors.log
log_errors_max_len = 0
; 别忘了设置日志文件的权限,确保Web进程有写入权限
我在项目中遇到过一个问题:日志文件越来越大,最后把磁盘撑爆了。所以建议配合日志轮转(log rotation)使用。Linux下可以用logrotate,每天切割一次,保留30天,基本够用。
3.4 三个配置的协同工作
这三个配置不是孤立的,它们是一条流水线:
- error_reporting 先筛选:哪些错误值得关注
- display_errors 决定是否展示给用户
- log_errors 决定是否写入日志
说白了,就是「筛出来→要不要给人看→要不要记下来」三步走。你可以在运行时用 ini_set() 临时修改这些配置,但注意:display_errors 如果脚本有致命错误(比如解析错误),在错误发生前可能来不及执行 ini_set()。所以php.ini里的配置才是最终保障。
一个小技巧:
如果你在开发环境想临时屏蔽某个页面的错误输出,可以用:
<?php
ini_set('display_errors', 0);
// 你的代码...
?>
但记得调试完改回来,不然容易漏掉问题。
3.5 实战建议:不同环境的配置模板
最后,我整理了一份我常用的配置模板,供你参考:
| 配置项 | 开发环境 | 测试环境 | 生产环境 |
|---|---|---|---|
| error_reporting | E_ALL | E_ALL & ~E_DEPRECATED | E_ALL & ~E_NOTICE & ~E_DEPRECATED |
| display_errors | On | Off | Off |
| display_startup_errors | On | Off | Off |
| log_errors | On | On | On |
| error_log | /tmp/php_errors.log | /var/log/php_errors.log | /var/log/php_errors.log |
记住一句话:开发环境要「看得见」,生产环境要「藏得住、记得牢」。这三个配置项虽然基础,但用好了能帮你省下大量排查问题的时间。嗯,今天就先聊到这,下一节咱们看看怎么在代码里自定义错误处理函数。