set_error_handler仅捕获E_WARNING、E_NOTICE、E_USER_ERROR等非致命错误,不处理E_ERROR、E_PARSE等导致脚本终止的错误;需配合register_shutdown_function兜底捕获致命错误。

set_error_handler 能捕获哪些错误
set_error_handler 只能捕获 PHP 运行时触发的 E_WARNING、E_NOTICE、E_USER_ERROR 等非终止类错误,**不处理 E_ERROR(如语法错误、致命错误)、E_PARSE、E_CORE_ERROR 和 E_COMPILE_ERROR**。这些错误发生时脚本已无法继续执行,set_error_handler 根本不会被调用。
常见误判场景:
- 把
echo $undefined_var;当成“页面崩溃”,其实它触发的是E_NOTICE,可被捕获 - 写错函数名如
file_get_contets(),实际抛出E_WARNING,也能捕获 - 但
function foo() { return(缺右括号)这类语法错误,set_error_handler完全无效
自定义错误处理器函数怎么写才安全
回调函数必须严格遵循签名:function($errno, $errstr, $errfile, $errline, $errcontext)。其中 $errcontext 是可选的,但**强烈建议忽略它**——它包含当前作用域所有变量的副本,可能引发内存泄漏或敏感信息泄露(比如数据库密码出现在 $errcontext['password'] 中)。
实操要点:
- 开头加
error_reporting(0)或检查$errno & error_reporting(),避免重复报告已被屏蔽的错误 - 不要在处理器里再触发错误(比如调用未定义函数),否则可能陷入递归死循环
- 若需记录日志,用
error_log()而非echo或print_r,防止干扰 AJAX 响应或 JSON 输出 - 返回
true表示“已处理,不再走默认逻辑”;返回false或不返回,则继续执行 PHP 默认错误处理(通常输出到屏幕或日志)
为什么 set_error_handler 后 500 页面还是显示默认错误
因为 set_error_handler 不影响 HTTP 状态码。即使你捕获了 E_WARNING 并静默处理,PHP 仍会返回 200 OK,浏览器看到的是空白或部分渲染内容,而非真正的错误页。
要真正呈现自定义错误页面,必须组合使用:
- 用
http_response_code(500)显式设置状态码 - 在处理器末尾
include 'error-500.php'或直接die(file_get_contents('error-500.html')) - 注意:如果错误发生在
header()已输出之后(如已 echo 内容),http_response_code()无效,此时只能靠前端 JS 检测响应体内容做 fallback
典型陷阱:error-500.php 本身再出错(比如 include 路径错),会导致白屏且无日志——务必确保错误页文件路径绝对可靠、内容极简、不含任何 PHP 逻辑。
和 register_shutdown_function 配合处理致命错误
set_error_handler 抓不到 E_ERROR,但 register_shutdown_function 总会在脚本结束时执行,配合 error_get_last() 可兜底捕获最后的致命错误。
关键点:
- 必须在脚本最开始注册,越早越好(比如入口文件第一行)
-
error_get_last()返回数组,需判断isset($error['type']) && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR]) - 此处同样要设
http_response_code(500),并加载静态 HTML 错误页(避免再执行 PHP) - 注意:
register_shutdown_function也会在正常结束时触发,所以不能无条件当错误处理
真正健壮的错误页方案,是 set_error_handler + register_shutdown_function 双覆盖,前者管运行时警告/通知,后者管崩溃级错误。两者日志格式最好统一,方便后续聚合分析。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











