必须在 set_error_handler() 回调中显式返回 true,否则 php 会继续执行默认错误输出,导致重复报错、页面乱码或 json 接口解析失败;它仅处理传统错误(如 e_warning),exception 和致命错误需分别用 set_exception_handler() 和 register_shutdown_function() 捕获。

最常犯的错误是:在 set_error_handler() 回调函数里直接 echo 或 print 错误信息,且未返回 true —— 导致 PHP 后续仍尝试输出原生错误,造成重复报错或页面乱码。
为什么不能在错误处理器里直接输出 HTML?
PHP 的错误处理机制默认会接管错误后中断默认行为,但前提是你的回调函数明确告诉它“我已处理完毕”。否则 PHP 会继续走默认流程(比如向浏览器输出裸错误),尤其当 display_errors = On 时,你会看到两遍错误:一遍是你 echo 的,一遍是 PHP 自己吐的。
常见表现:
- 页面顶部突然出现
Warning: Undefined array key "xxx",紧接着你自己的echo "捕获到警告" - JSON 接口返回了混杂的 HTML 错误文本,导致前端解析失败
- 日志里同一错误被记录两次
set_error_handler() 必须返回 true 才生效
这个返回值不是可选的——它是 PHP 判断“是否已接管”的唯一依据。返回 false、null 或不写 return,等同于没接管,PHP 会照常抛出原始错误。
正确写法示例:
set_error_handler(function($errno, $errstr, $errfile, $errline) {
error_log("[$errno] $errstr in $errfile:$errline");
// 不要 echo/print
return true; // ← 关键!必须显式返回 true
});
注意点:
- 不要在回调里调用
trigger_error(),可能引发递归调用 - 避免在回调中触发新错误(如访问未定义变量),否则可能进入无限错误循环
- 如果只想处理部分错误级别(比如忽略
E_NOTICE),需在函数开头加判断:if (!($errno & (E_WARNING | E_ERROR))) return false;
混淆错误(Error)和异常(Exception)的处理方式
很多新手以为 set_error_handler() 能捕获 throw new Exception 或 PHP 7+ 的 Error 类对象——它不能。这两类问题需要分开处理:
-
set_error_handler():只处理传统 PHP 错误(E_WARNING、E_NOTICE等) -
set_exception_handler():处理所有Exception和Error实例(PHP 7+) -
register_shutdown_function():用于捕获致命错误(如E_PARSE、内存耗尽),因为它们无法被set_error_handler()拦截
漏掉其中任一环节,都会导致某些错误“消失”或直接崩溃脚本。
真正容易被忽略的是:错误处理器本身也是 PHP 代码,它受当前错误报告级别控制。如果在 php.ini 中把 error_reporting 设为 0,你的自定义处理器根本不会被调用——连初始化都跳过了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











