
PHP 错误级别有哪些,哪些会中断脚本执行
PHP 的错误级别不是“警告”“错误”这种模糊分类,而是由整数常量定义的位掩码值,直接决定错误是否显示、是否记录、是否中止脚本。关键在于:E_ERROR、E_PARSE、E_CORE_ERROR 这三类会立即终止脚本;其余如 E_WARNING、E_NOTICE、E_DEPRECATED 默认不中断执行,但可能被 set_error_handler() 捕获或在严格模式下升级为致命错误。
常见误解是认为 E_USER_ERROR 一定致命——其实它只是触发 trigger_error(),是否中止取决于错误处理器返回值(默认不中止),除非你手动 die() 或配置了 error_reporting 包含它且未设自定义处理器。
-
E_ERROR:运行时致命错误(如调用不存在函数),脚本立刻停止 -
E_WARNING:非致命运行时警告(如 include 失败),脚本继续 -
E_NOTICE:潜在问题提示(如访问未定义变量),默认不显示,开发环境建议开启 -
E_DEPRECATED:功能已弃用(如mysql_connect()),PHP 8.0+ 默认不报告,但仍在E_ALL中
error_reporting() 设置不当导致错误“消失”
很多线上环境看不到 E_NOTICE 或 E_DEPRECATED,不是没发生,而是 error_reporting 被设成了 E_ALL & ~E_NOTICE 或更激进的 0。尤其注意:CLI 模式和 Web 模式可能使用不同 php.ini,ini_set('error_reporting', ...) 只影响当前请求,无法覆盖 php.ini 中的 error_reporting = 0。
- 开发环境推荐:
error_reporting(E_ALL | E_STRICT)(PHP 5.x)或error_reporting(E_ALL)(PHP 7+) - 生产环境不建议关所有错误,至少保留
E_ERROR | E_WARNING | E_PARSE -
error_reporting(-1)是最安全的写法,等价于全部开启(包括未来新增级别) - 如果用了
set_error_handler()却没处理E_ERROR,该错误仍会绕过处理器直接中止脚本
display_errors 和 log_errors 的实际影响
display_errors 控制错误是否输出到页面或 CLI 终端,log_errors 控制是否写入日志文件。两者互不影响,但容易混淆:关掉 display_errors 不代表错误不发生,也不代表不记录——只要 log_errors = On 且 error_log 配置有效,错误仍会进日志。
立即学习“PHP免费学习笔记(深入)”;
- 线上环境必须关
display_errors(防止敏感路径/变量泄露),开log_errors -
error_log = /var/log/php/error.log必须确保 PHP 进程有写权限,否则错误会静默丢失 - CLI 脚本默认
display_errors = On,但若重定向 stdout/stderr,错误可能被吞掉,建议显式设置ini_set('display_errors', 'stderr') -
display_errors = stderr(PHP 7.2+)比On更可控,避免 HTML 混淆
PHP 8 的变化:TypeError 和 ValueError 不属于传统错误级别
PHP 8 引入的 TypeError 和 ValueError 是异常(Throwable),不是传统错误级别,不会被 set_error_handler() 捕获,只能用 try/catch。这意味着:即使你把 error_reporting 设为 E_ALL,也看不到它们的“错误报告”,只会看到未捕获异常的 fatal error 提示。
- 函数参数类型错误(如传
string给期望int的参数)抛TypeError - 内置函数参数值非法(如
json_decode(''))抛ValueError - 它们的错误信息格式和传统
E_*不同,例如:Fatal error: Uncaught TypeError: ... - 不能靠
error_reporting屏蔽它们,必须用异常处理逻辑兜底
真正难调试的,往往是 E_NOTICE 在开发期被忽略,上线后因 error_reporting 关闭而彻底隐身,直到某次变量名拼错引发空数组遍历崩溃——这时候才想起,当初该让 notice 响起来。










