frankenphp 的错误页由 caddy 控制;因 frankenphp 是 caddy 插件,未命中 php 路径时由 caddy 返回默认 404,需通过 try_files {path} /index.php 强制转发至 laravel 入口才能启用其错误页。

FrankenPHP 的错误页由谁控制?
不是 Laravel,而是 Caddy。FrankenPHP 本质是 Caddy 的一个插件,php_server 指令只负责 PHP 脚本执行;一旦请求没命中 PHP(比如直接访问 /missing.css 或 /nonexistent),Caddy 就会走自己的错误处理逻辑,返回它内置的默认 404 页面——和 Laravel 的 resources/views/errors/404.blade.php 完全无关。
怎么让 Laravel 错误页生效?必须走 PHP 入口
关键前提是:请求得进到 index.php,Laravel 的异常处理机制才有机会介入。Caddy 默认对不存在的路径直接返回 404,根本不会转发给 PHP。所以你需要显式把“可能不存在”的路径也交给 php_server 处理:
- 在 Caddyfile 的
php_server块里加try_files {path} /index.php(注意斜杠不能少) - 确保
root指向的是public/目录,且该目录下有index.php - 不要依赖 Caddy 的
file_server自动 fallback,它不触发 PHP
正确配置片段示例:
localhost {
root * public/
php_server {
try_files {path} /index.php
}
encode zstd br gzip
}
为什么改了 Caddyfile 还是看到 Caddy 默认页?
常见卡点:
-
try_files写成try_files {path} index.php(缺开头斜杠)→ Caddy 找不到index.php,直接 fallback 到自身 404 - Laravel 的
APP_DEBUG=true→ 500 异常会显示调试页,但 404 仍走 Caddy;只有APP_DEBUG=false时才会渲染resources/views/errors/404.blade.php - 修改了
404.blade.php但没清缓存 → 必须运行php artisan view:clear,否则旧编译文件还在用 - Caddy 配置没重载 → 修改 Caddyfile 后要重启 FrankenPHP 进程或发送
SIGHUP(Docker 下用docker kill -s HUP <container-id></container-id>)
500 错误页为啥还是空白或 Caddy 默认页?
因为 PHP 执行崩溃(如语法错误、扩展缺失、内存溢出)发生在 Laravel 启动前,index.php 根本没跑完,更别说进入 Handler 类。这种错误只能靠 Caddy 或 FrankenPHP 日志定位:
- 查 FrankenPHP 启动日志,看是否有
PHP Parse error或Segmentation fault - 确认
php.ini中display_errors = Off且log_errors = On,错误会写入 Caddy 的 error log - 临时把
APP_DEBUG=true,如果此时能看到 PHP 错误信息,说明问题在框架启动阶段,和 Laravel 错误页无关
真正能被 500.blade.php 捕获的,仅限 Laravel 应用层抛出的未捕获异常,比如控制器里写了 throw new Exception()。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











