frankenphp 的 public 目录必须是 web 根目录,否则 index.php 404、静态资源无法访问且敏感文件暴露;需通过 -d public/、caddyfile root * /path/public 或 docker 挂载精准指定,确保 root 与 php_server 路径一致。

FrankenPHP 的 public 目录必须是 Web 根目录
FrankenPHP 不会自动“猜”你的项目结构,它默认把启动时的当前目录当作 document root —— 但绝大多数 PHP 框架(Laravel、Symfony、ThinkPHP)要求 public/ 是实际对外服务的根。如果设错,连 index.php 都 404,后续一切路由、重写都无从谈起。
常见错误现象:
- 访问
https://localhost:8080返回 404,且curl -I http://localhost:8080/index.php也是 404 - Caddy 日志里反复出现
file not found或no such file or directory - 浏览器开发者工具 Network 面板显示所有请求状态码都是 404,包括 CSS/JS 文件
正确做法取决于你用哪种方式启动:
- 命令行直接运行:
frankenphp -d public/(-d指定 document root) - Docker 启动:确保挂载路径指向项目根目录,并确认容器内 Caddyfile 的
root * /app/public(不是/app) - 单文件二进制(
frankenphp build生成):构建时无需额外指定,但前提是执行frankenphp build的当前目录下存在public/,且其中包含有效的index.php - Caddyfile 配置:显式写
root * /path/to/your-project/public,不能省略public这一级
为什么不能把项目根目录当 Web 根
因为框架的敏感目录(如 app/、config/、.env)会暴露在 URL 下,造成严重安全风险。FrankenPHP 没有内置路径屏蔽逻辑,它完全依赖你设置的 root 范围来决定哪些文件可被直接访问。
例如,若错误地设为 root * /var/www/myapp,那么访问 https://example.com/.env 就可能直接返回明文配置 —— 这在生产环境是致命漏洞。
验证是否生效的最简方法:
- 在
public/下放一个test.txt,内容为ok - 启动 FrankenPHP 后访问
http://localhost:8080/test.txt,应返回ok - 再访问
http://localhost:8080/config/database.php,应返回 404(而不是文件内容)
Caddyfile 中 root 和 php_server 的配合关系
root 定义静态资源查找起点,php_server 决定哪些请求交给 PHP 处理 —— 二者必须对齐,否则会出现“能访问 PHP 文件但无法解析 PATH_INFO”或“静态资源 404 但 PHP 路由却意外生效”这类矛盾行为。
典型错误配置:
root * /var/www/myapp php_server
这会让 Caddy 去 /var/www/myapp 找 index.php,但实际它在 /var/www/myapp/public/index.php,所以 PHP 请求根本不会触发。
正确写法(以 Laravel 为例):
root * /var/www/myapp/public php_server
此时 php_server 默认匹配所有 .php 文件,并自动 fallback 到 index.php;所有非 PHP 请求(CSS/JS/IMG)由 Caddy 直接读取磁盘返回,不经过 PHP 解释器。
注意:php_server 指令本身不继承 root,它只负责“把匹配到的请求交给 PHP 运行时”,真正的文件定位全靠前面的 root 和 try_files 行为支撑。
worker 模式下 public 目录位置不能动态改
启用 worker 模式后,FrankenPHP 会在进程启动时预加载整个应用(包括自动加载器、配置、容器),此时 public/ 的路径已固化。如果你在 public/ 外部硬编码了路径(比如在 config/app.php 里写死 __DIR__.'/../storage'),那没问题;但若依赖运行时计算(如 dirname($_SERVER['SCRIPT_FILENAME'])),就可能出错 —— 因为 worker 进程的入口不再是 index.php,而是 worker.php。
所以 worker 模式下更要确保:
-
public/是唯一且稳定的 Web 根,不通过 PHP 代码动态推导 - 所有路径相关配置(缓存目录、日志路径、上传临时目录)都使用绝对路径或基于
__DIR__的相对路径 - 不要在
public/index.php里做任何影响全局路径判断的chdir()或set_include_path()
最易被忽略的一点:Docker 或 systemd 启动时,工作目录(WorkingDirectory)和 root 配置必须一致。比如 systemd service 文件里写了 WorkingDirectory=/var/www/myapp,但 Caddyfile 里写的是 root * /var/www/myapp/public,那就没问题;但如果 Caddyfile 写成 root * ./public,就会因相对路径解析失败导致 404。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











