默认 php_server 模板在 Laravel 下不 work,因其 try_files {path} index.php 未透传原始 URI 且缺失 split_path 和 PATH_INFO 设置,导致路由解析失败而 404。

直接用官方 Caddyfile 模板,但必须删掉 php_server 里的 try_files 默认值——否则 Laravel 路由会 404。
为什么默认 php_server 模板在 Laravel 下不 work
FrankenPHP 官方 Docker 镜像和独立二进制自带的 Caddyfile(比如 caddy/frankenphp/Caddyfile)里,php_server 指令默认写的是:
php_server { try_files {path} index.php }
这会导致两个问题:
-
{path}是原始请求路径,比如/user/123,Caddy 会先查public/user/123文件——显然不存在,于是 fallback 到index.php,但没带PATH_INFO或QUERY_STRING,Laravel 的路由解析器收不到原始 URI,全部变成首页或 404 - 它没显式启用
fastcgi_split_path_info类似逻辑,而 Laravel 依赖这个把/index.php/user/123拆成脚本路径 + 路由路径
所以你得手动补上路由透传逻辑。
立即学习“PHP免费学习笔记(深入)”;
php_server 必须加的三个参数
在 php_server 块里,只保留这三行(删掉默认 try_files):
-
root public/:明确 Web 根目录,不能省(否则index.php找不到) -
split_path /index.php:告诉 FrankenPHP 把/index.php/xxx拆成 PHP 脚本路径 +PATH_INFO环境变量,Laravelpublic/index.php依赖它还原原始路由 -
env PATH_INFO {http.request.uri.path}:兜底补一个PATH_INFO,防止某些重写规则漏掉(尤其本地开发用localhost时)
完整最小可用块长这样:
localhost {
root public/
php_server {
split_path /index.php
env PATH_INFO {http.request.uri.path}
}
encode zstd br gzip
}
Docker 和本地二进制的 Caddyfile 差异点
两者配置结构一致,但注意这些细节:
- Docker 场景下:
root路径是容器内路径,挂载$PWD:/app后,root必须写public/(不是/app/public/),因为 Caddy 当前工作目录就是/app - 本地二进制场景下:确保你执行
frankenphp run时在 Laravel 项目根目录,root public/才能正确解析 - HTTPS 自动启用:只要域名不是
localhost,Caddy 会自动走 Let’s Encrypt;localhost则用自签名证书,浏览器要手动点“继续访问” - 别碰
frankenphp全局块里的num_threads:Laravel 在 classic 模式下不依赖它,设了反而可能因线程数过多触发 PHP 内存限制
真正容易被忽略的是 split_path ——它不像 Nginx 的 fastcgi_split_path_info 那样有正则匹配,FrankenPHP 的 split_path 只认字面量前缀,必须严格写成 /index.php,写成 index.php 或 public/index.php 都无效。



















