thinkphp 8.0多应用路由404的根本原因是子应用路由文件未被自动加载,必须显式调用route::import('admin', 'admin')等语句导入,且app/controller目录必须删除,否则强制降级为单应用模式。

ThinkPHP 8.0项目启用多应用后,访问/admin/login或/api/v1/user始终返回404,不是控制器写错、也不是域名没配好,而是app/admin/route/app.php和app/api/route/app.php这两个文件压根没被框架读取——框架不会自动扫描子应用目录下的路由文件,必须人工干预加载路径。
确认多应用基础环境已就绪
打开命令行,进入项目根目录,执行:php think app:create admin。若提示“Command 'app:create' not found”,说明未安装topthink/think-multi-app扩展,立即运行composer require topthink/think-multi-app并重试。
检查app/admin/目录是否完整生成:必须包含controller/、route/、config/和middleware.php;若只有空文件夹或缺少route/app.php,说明命令执行失败或扩展未注册,需手动创建app/admin/route/app.php并确保首行为use think\facade\Route;。
【app/controller目录必须已被删除】。只要该目录存在,框架将强制降级为单应用模式,所有Route::import()调用均失效,且不报任何警告。
在全局入口显式导入子应用路由
编辑app/route/app.php,清空全部原有路由定义,只保留导入语句:
Route::import('admin', 'admin');Route::import('api', 'api');Route::import('mobile', 'mobile');
第二个参数必须与app/下的子目录名完全一致,大小写敏感。比如子目录是app/Admin,但你写了'admin',路由就不会加载——框架会静默跳过,不报错也不提示。
这一步不可省略。ThinkPHP 8.0默认不扫描app/*/route/路径,【不调用Route::import(),对应子应用的任何路由都永远不会生效】。
验证子应用路由文件是否真正被加载
方法一:临时调试法
在app/admin/route/app.php第一行插入exit('admin route loaded');,然后访问/admin/login。如果页面输出admin route loaded,说明文件已加载;若仍返回404或空白页,说明Route::import()未执行或路径名不匹配。
方法二:命令行校验法
执行php think route:list --name=admin(假设你为admin路由设置了name前缀)。若无任何输出,证明导入失败;若有列表显示,则说明导入成功且命名规则正确。
注意:若使用Swoole启动服务(php think swoole),必须额外在route/app.php中完成导入——Swoole模式下,框架只加载此处,app/admin/route/等子路径完全被忽略。
修复子应用路由内部常见错误
第一步:打开app/admin/route/app.php,删除所有Route::group('admin', [...])包裹结构。
第二步:直接书写扁平化路由,例如:Route::get('login', 'Index/login');
第三步:确保控制器类实际存在于app/admin/controller/Index.php,且命名空间为app\admin\controller。
如果保留Route::group('admin', [...]),最终URL会变成/admin/admin/login,因为多应用模式已通过目录隔离,再加一层group前缀属于重复嵌套。
这一步做完后,访问http://yoursite.com/admin/login即可正常进入登录页。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











