frankenphp 子目录部署时 /register 404 的根本原因是请求未抵达 index.php:其默认不解析 .htaccess、不自动设置 script_name 和 path_info,导致 symfony 无法正确解析子目录路径(如 /myapp/register),路由匹配失败。

FrankenPHP 部署 Symfony 子目录项目时,/register 这类路由返回 404,不是 Symfony 路由没注册,而是请求压根没进 index.php —— FrankenPHP 默认不自动处理子目录下的重写逻辑,public/ 目录被当作静态资源根,导致 /subdir/register 被当成物理路径查找,而非转发给 index.php。
为什么 FrankenPHP 在子目录下不识别 Symfony 路由
FrankenPHP 的 server.php 或内置 HTTP 服务器默认以当前工作目录为 Web 根,不解析 .htaccess,也不自动启用 PATH_INFO 模式。当项目部署在 https://example.com/myapp/ 这样的子目录时,Symfony 生成的 URL(如 myapp/register)会被 FrankenPHP 当作静态路径尝试命中 public/register,而不会触发 public/index.php 的前端控制器逻辑。
关键点:
-
php bin/console router:match /register成功 → 证明 Symfony 内部路由存在且有效 - 浏览器访问
/myapp/register404 → 请求未抵达index.php,是 Web 服务器层拦截 - FrankenPHP 不读取
.htaccess,Nginx/Apache 那套规则完全无效
必须设置 SCRIPT_NAME 和 PATH_INFO 才能走通
Symfony 在子目录中依赖正确的 CGI 环境变量推导当前请求路径。FrankenPHP 默认不注入这些,需显式配置。否则 $request->getPathInfo() 返回 /,所有路由匹配都从根开始算,自然找不到 /register。
实操方法(任选其一):
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 启动 FrankenPHP 时加环境变量:
SCRIPT_NAME=/myapp/index.php PATH_INFO=/register frankenphp serve - 在
public/index.php开头手动修正(临时调试用):$_SERVER['SCRIPT_NAME'] = '/myapp/index.php'; $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'] ?? ''; // 剥离子目录前缀,只保留路径部分(如 /myapp/register → /register) $prefix = '/myapp'; if (str_starts_with($_SERVER['PATH_INFO'], $prefix)) { $_SERVER['PATH_INFO'] = substr($_SERVER['PATH_INFO'], strlen($prefix)); } - 使用 FrankenPHP 的
frankenphp.yaml配置(推荐):apps: - directory: . index_file: public/index.php script_name: "/myapp/index.php" # 注意:FrankenPHP 1.2+ 支持 path_prefix,但需配合路由重写 path_prefix: "/myapp"
routes.yaml 或注解里的路径别写子目录前缀
Symfony 路由定义永远只写「应用内路径」,不包含部署子目录。比如你部署在 /myapp/,控制器里还是写:
#[Route('/register', name: 'app_register')],而不是 #[Route('/myapp/register', ...)]。后者会导致 router:generate 输出错误 URL,且 router:match 在 CLI 下反而无法匹配(因为 CLI 没有子目录上下文)。常见错误:
- 在
config/routes.yaml中硬编码prefix: '/myapp'→ 会双重叠加,变成/myapp/myapp/register - 用
url()Twig 函数生成链接时没传relative=false→ 生成相对路径register,在子目录下跳转错位 - 没调用
$request->getBasePath()或asset()Twig 函数处理静态资源路径 → CSS/JS 404
验证是否真进到 Symfony 而不是被 FrankenPHP 拦截
最直接的办法:在 public/index.php 最开头加一行:
file_put_contents('/tmp/frankenphp-debug.log', print_r($_SERVER, true), FILE_APPEND);,然后访问子目录 URL,检查日志里 SCRIPT_NAME、PATH_INFO、REQUEST_URI 的值是否符合预期。如果 PATH_INFO 是空或 /,说明 FrankenPHP 没把路径透传进来;如果 SCRIPT_NAME 是 /index.php(缺子目录),那路由必然错乱。这两个变量不对,后面所有 Symfony 配置都白搭。
子目录部署的复杂点不在 Symfony 本身,而在 FrankenPHP 如何把原始 HTTP 路径准确拆解并喂给 PHP 的 CGI 接口 —— 这一步漏掉,就等于没装发动机,光调方向盘没用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










