ThinkPHP 6 关闭 app_debug 后仍白屏,是因为 error_page 配置需配合 exception_handle 处理器生效,且 Nginx 的 fastcgi_intercept_errors 不能开启,否则会劫持错误响应。

ThinkPHP 6 的 app_debug 关闭后为什么还是显示白屏而不是自定义错误页
因为默认情况下,app_debug = false 只是关闭了调试信息输出,但并未自动启用「友好错误页面」——它依赖于 exception_handle 配置和异常处理器是否真正接管了 Throwable。
常见现象:生产环境关掉 app_debug,访问一个不存在的路由或触发致命错误,页面直接空白或只返回 HTTP 500 状态,没走你写的 404.html 或 500.html。
- 确认
config/app.php中'exception_handle' => \think\exception\Handle::class没被注释或覆盖 - 确保
public/static/error/(或你配置的error_page目录)下存在对应状态码的 HTML 文件,如404.html、500.html - 检查
config/app.php是否设置了'error_page' => '/static/error/{code}.html'(注意路径需以/开头,且为 Web 可访问路径) - 如果用了 Nginx,确认没开启
fastcgi_intercept_errors on—— 它会劫持 PHP 返回的 4xx/5xx 响应,导致 ThinkPHP 的错误页不生效
如何让 404 错误真正走自定义页面而非默认异常堆栈
ThinkPHP 的 404 不是靠 HTTP 状态码触发的,而是由路由未匹配时抛出的 think\exception\HttpException(code=404)驱动的。要让它渲染自定义页,关键在异常处理器能否识别并委托给 error_page。
- 不要手动在控制器里写
throw new HttpException(404)后期望自动跳转——它仍走异常流程,但需确保Handle::render()最终调用$this->renderExceptionPage($e) - 推荐做法:在
app/exception/Http.php(自定义异常类)中重写render()方法,对$e->getStatusCode() === 404的情况,显式返回view('error/404') - 若用的是模板引擎,确保
view_path包含app/view/error/,且该目录下有404.html;否则即使配置了error_page,底层仍 fallback 到空响应
config/app.php 里的 error_page 和 exception_handle 怎么配才不冲突
error_page 是静态资源路径映射,仅对框架内部抛出的 HttpException 生效;而 exception_handle 是 PHP 异常拦截入口,决定谁来处理所有 Throwable。两者必须协同,不能只配其一。
立即学习“PHP免费学习笔记(深入)”;
-
'error_page' => '/static/error/{code}.html':表示当抛出HttpException(404)时,重定向到该 URL(注意是浏览器跳转,非服务端包含) -
'exception_handle' => \app\exception\Handler::class:必须继承think\exception\Handle,并在render()中调用parent::render($e),否则error_page逻辑不会触发 - 如果自定义
Handler里写了return response(...)->code(404)而没调用父类方法,error_page就完全失效 - 验证方式:临时在
Handler::render()开头加var_dump(get_class($e)); die;,看 404 时是否进来的是HttpException
为什么自定义 500 页面在 PDO 连接失败时没显示
数据库连接异常(如 PDOException)属于 PHP 原生异常,不继承 HttpException,因此绕过了 error_page 机制,直接由 exception_handle 处理。这时候你得自己兜底。
- 在自定义
Handler::render()中判断:if ($e instanceof \PDOException || $e instanceof \Error),然后手动返回view('error/500') - 避免直接 echo 或 exit,否则破坏框架生命周期;要用
response()->view('error/500', [], 500) - 注意
500.html里别引用 JS/CSS 相对路径(如./css/app.css),生产环境容易 404——统一用/static/css/app.css或{:asset('css/app.css')} - 如果用了多语言,
500.html不会自动加载语言包,需要在view('error/500')里手动传参或改用纯静态 HTML
fastcgi_intercept_errors 和自定义 Handler 中忘记调用父类 render —— 这两个点卡住,其他都白配。



















