set_error_handler无法捕获致命错误,需组合register_shutdown_function(查error_get_last)、set_exception_handler及正确error_reporting配置三者协同处理。

php错误处理函数怎么换:set_error_handler 不能捕获所有错误
直接说结论:set_error_handler 只能捕获 E_WARNING、E_NOTICE、E_USER_* 这类非终止性错误,对 E_ERROR、E_PARSE、E_CORE_ERROR 等致命错误完全无效。想“换掉”默认错误处理,得组合使用多个机制。
捕获致命错误只能靠 register_shutdown_function + error_get_last
PHP 脚本终止前会触发 register_shutdown_function,这是唯一能“看到”致命错误的机会。但要注意:它不是实时捕获,而是事后检查;且需手动判断是否真发生了未捕获的致命错误。
-
error_get_last()必须在 shutdown 函数里立刻调用,延迟调用可能返回空(比如被后续 warning 覆盖) - 只检查
error_get_last()['type']是否属于E_ERROR、E_PARSE、E_COMPILE_ERROR等,避免把正常 exit 当作错误 - 该方法无法阻止脚本退出,只能做日志、上报或兜底响应
register_shutdown_function(function () {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_COMPILE_ERROR])) {
error_log("Fatal error: {$error['message']} in {$error['file']}:{$error['line']}");
// 此处可输出自定义错误页或触发告警
}
});
异常和错误要分开处理:set_exception_handler 不等于 set_error_handler
很多人混淆这两者。set_exception_handler 只接管未被捕获的 Exception 和 Error(PHP 7+ 的 Throwable),而 set_error_handler 只管传统错误。两者必须同时设置才完整。
- PHP 7+ 推荐统一用
set_exception_handler处理Throwable,包括Error子类(如ParseError、FatalError) -
set_error_handler中可用throw new ErrorException($message, $code, $severity, $file, $line)把传统错误转为异常,再由异常处理器统一处理 - 注意:
ErrorException是Exception的子类,不是Error,所以不会被catch (Error $e)捕获
别忽略 error_reporting 配置的影响
即使设置了 set_error_handler,如果当前 error_reporting 级别不包含某类错误,它根本不会被触发。比如 error_reporting(0) 下,set_error_handler 对任何错误都失效。
立即学习“PHP免费学习笔记(深入)”;
- 开发环境建议设为
E_ALL,生产环境至少保留E_ALL & ~E_NOTICE & ~E_DEPRECATED - 用
ini_set('error_reporting', E_ALL);动态修改时,必须在set_error_handler之前执行 -
display_errors = Off和log_errors = On是基础配置,否则错误既不显示也不记录
set_error_handler,致命错误靠 register_shutdown_function 补漏,异常和 PHP 7+ 的 Error 类型交给 set_exception_handler。三者缺一不可,且顺序和配置细节稍有偏差就失效。











