PHP自定义错误处理 无重定向发送其他文档内容实现方法
PHP实现无重定向自定义500错误响应(复现ErrorDocument效果)
核心逻辑是在脚本初始化阶段注册全局错误、异常、致命错误捕获处理器,触发错误时清空已生成的响应内容,直接返回自定义错误页内容,全程不做跳转,完全替代原请求的响应内容。
实现代码
将以下代码放在项目入口文件的最顶部,保证在所有业务逻辑执行前加载完成:
<?php // 开启输出缓冲,确保可以清空业务逻辑提前输出的内容 ob_start(); /** * 输出自定义500错误响应 * @param string $customErrorPage 自定义500页面的文件路径 */ function return_custom_500(string $customErrorPage): void { // 清空多层输出缓冲区的所有已有内容 while (ob_get_level() > 0) { ob_end_clean(); } // 设置500响应状态码 http_response_code(500); // 输出自定义错误页内容 if (is_file($customErrorPage) && is_readable($customErrorPage)) { require $customErrorPage; } else { // 兜底输出,避免自定义页面不存在时返回空白 echo '<h1>500 Internal Server Error</h1><p>服务器内部错误,请稍后重试。</p>'; } // 终止脚本执行,不再输出原请求的其他内容 exit; } // 捕获致命错误(语法错误、调用未定义方法、类不存在等直接触发500的场景) register_shutdown_function(function () { $lastError = error_get_last(); $fatalErrorTypes = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR]; if ($lastError && in_array($lastError['type'], $fatalErrorTypes)) { return_custom_500(__DIR__ . '/public/500.html'); } }); // 捕获未被try/catch处理的异常 set_exception_handler(function (Throwable $e) { // 可在此处添加错误日志记录逻辑,例如将异常信息写入日志文件 return_custom_500(__DIR__ . '/public/500.html'); }); // 捕获普通级别错误,可按需配置是否转为500响应 set_error_handler(function ($errNo, $errStr, $errFile, $errLine) { // 忽略被@符号抑制的错误 if (!(error_reporting() & $errNo)) { return false; } // 可在此处添加错误日志记录逻辑 return_custom_500(__DIR__ . '/public/500.html'); });
关键注意点
- 代码必须在所有业务逻辑前加载,否则部分提前触发的错误无法被捕获
- 自定义错误页的路径填写为自己项目中实际存放500页面的绝对路径,页面内不要包含复杂逻辑,避免触发二次错误导致递归调用处理器
- 该方案无法捕获PHP进程启动阶段的错误(例如扩展加载失败、php.ini配置非法),这类场景仍需要在Web服务层做兜底配置
- 整个错误响应过程在当前请求内完成,不会返回3xx跳转状态码,和原生ErrorDocument的行为完全一致
- 如果业务逻辑中已经提前输出了部分内容,缓冲区清空逻辑会将这部分内容完全清除,不会和错误页内容拼接返回
内容的提问来源于stack exchange,提问作者Jeweled
相关产品推荐
相关产品推荐

