ThinkPHP 多应用模式下 `route.php` 我配了八遍,前端请求还是 404:原来 `app_map` 把应用名"吃"掉了

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
站长杂谈 44 浏览 13 回复

上周给客户改个老项目,从单应用切到多应用模式。本地环境跑得好好的,一部署到测试机,所有接口集体 404。我盯着 `route/app.php` 看了二十分钟,路由规则写得明明白白,咋就不生效呢?

先说我怎么排查的,给同样踩坑的兄弟参考:

第一步:确认路由文件到底加载没

我在 `route.php` 第一行直接 `die('route loaded')`,刷新页面,没反应。好,文件压根没执行。这时候别急着改路由,先去看应用入口对不对。

多应用模式下,我配了 `app_map` 做应用映射:

'app_map' => [
    'api' => 'api',      // 域名/api/xxx 指向 api 应用
    'admin' => 'admin',
],

问题就出在这。我前端请求的 URL 是 `/api/v1/user/list`,但 `app_map` 匹配到 `api` 后,会把 `api` 这一段从 URL 里抹掉,实际进入路由解析的是 `/v1/user/list`。而我 `route/app.php` 里写的是:

Route::get('api/v1/user/list', 'v1.User/index');

前面多了个 `api/`,当然匹配不上。本地为啥能跑?因为我本地没配 `app_map`,用的默认应用绑定,URL 完整进路由,反而能对上。

第二步:钩子也不触发,连带坑

路由不通之后,我顺手测试了个全局中间件,发现 `app_init` 钩子里的日志也没写进去。当时心里一凉,以为整个应用生命周期都崩了。后来才反应过来:请求在路由匹配阶段就 404 了,根本没走到中间件和钩子执行那一步。

这俩问题其实是一个根子,别被表象带偏去查钩子注册。

第三步:多应用路由文件的"隐身"规则

ThinkPHP 多应用模式下,路由文件加载顺序是:

1. `route/route.php`(全局,所有应用共享)
2. `route/应用名/route.php`(应用专属)
3. `应用目录/route/route.php`(应用内部)

我之前把路由写在 `route/api/route.php`,但 `app_map` 映射后应用标识变了,文件路径对不上。最后统一收拢到 `route/route.php`,用路由分组做应用隔离,反而清爽:

Route::group('api', function () {
    Route::get('v1/user/list', 'api/v1.User/index');
})->app('api');

一点血泪总结

多应用模式切之前,建议先把 `app_map`、`domain_bind`、`deny_app_list` 这几个配置打印出来,对着 URL 走一遍解析流程。我这次就是太相信"本地能跑",没意识到本地和测试机的应用映射配置差了一条。

还有,路由不生效时,`php think route:list` 这个命令能救命,但它只列当前默认应用的路由。多应用下要加 `--app api` 指定应用名,我愣是查了半小时文档才看见这参数。

现在项目上线了,我把 `app_map` 的映射逻辑和路由实际匹配路径写进了项目 README,下次谁再接这个锅,至少不用从头踩一遍。

评论13
回复 · 13
Xena
Xena 新手 · #13 ·
同求,期待更新
Kate
Kate 新手 · #12 ·
已解决,谢谢楼主
郭英怡
郭英怡 新手 · #11 ·
学到了,顶一下
未央
未央 新手 · #10 ·
同求,期待更新
Ivy
Ivy 新手 · #9 ·
写得很清楚,收藏了
Knox
Knox 新手 · #8 ·
已解决,谢谢楼主
GraceWei
GraceWei 新手 · #7 ·
学到了,顶一下
Drew
Drew 新手 · #6 ·
写得很清楚,收藏了
浪漫的草莓
浪漫的草莓 新手 · #5 ·
感谢分享!
MayaPark
MayaPark 新手 · #4 ·
同求,期待更新
CoolKid🌸
CoolKid🌸 新手 · #3 ·
同求,期待更新
安然95
安然95 新手 · #2 ·
同求,期待更新
安然95
安然95 新手 · #1 ·
同求,期待更新
微信客服 微信客服