thinkphp 6.x 默认不启用多应用模式,需删除 app/controller 等目录、开启 auto_multi_app、安装 think-multi-app 并生成应用目录;路由须放应用内,域名绑定依赖 domain_bind 配置且需清缓存。

多应用模式默认是否启用?
ThinkPHP 6.x 默认**不启用多应用模式**,整个项目从单应用起步;而 ThinkPHP 5.x 默认就是多模块(多应用)结构,Application 目录下天然带 index、admin 等子目录。
这导致一个常见错误现象:php think build admin 执行后访问报错 “app\controller\Index not found”,因为 TP6 启动时发现 app/controller/ 存在,就认定是单应用——它压根没进多应用解析流程。
- TP6 判断逻辑很朴素:
is_dir(app/controller)为 true → 当前是单应用;否则才走多应用初始化 - 想启用多应用,必须先删掉
app/controller(及 model、middleware 等同级目录) - 再执行
composer require topthink/think-multi-app(注意:必须在项目根目录下运行) - 最后用
php think build index生成首个应用目录
应用目录路径和命名空间怎么对得上?
TP6 多应用的目录结构是 app/index/controller/Index.php,对应命名空间 app\index\controller\Index;而 TP5 是 application/index/controller/Index.php,命名空间为 app\index\controller\Index ——表面相似,但根路径不同,自动加载规则也变了。
- TP6 完全依赖 Composer 的 PSR-4,
app/ 是顶级命名空间起点,所以 app/index/ 就是 app\index\
- TP5 的
Application 目录名首字母大写,且实际注册的自动加载前缀是 app\,但路径映射靠框架自己维护,不严格对齐 PSR-4
- 新增一个
app/api/controller/User.php 后,必须运行 composer dump-autoload -o,否则类找不到
- 如果手动改过命名空间(比如写成
app\api\v1\controller\User),物理路径就必须是 app/api/v1/controller/User.php,少一层或多一层都会触发 Class not found
路由定义位置和域名绑定怎么配才生效?
TP6 的路由文件必须放在每个应用自己的目录下,比如 app/index/route/app.php,不能再像 TP5 那样统一写在根目录 route/route.php 中。
- 域名绑定只在多应用模式下起作用,配置项是
app.domain_bind,写在 config/app.php 里
- 示例配置:
'domain_bind' => ['api.example.com' => 'api', 'admin.example.com' => 'admin']
- 注意:绑定后访问
api.example.com/user/list,TP6 才会把请求路由到 app/api 下的控制器;如果直接访问 localhost:8000/api/user/list,仍走单应用逻辑(除非关掉 app/controller 并确保 app.auto_multi_app = true)
- 常见坑:改了
domain_bind 却没清路由缓存,或没在 app/api/route/app.php 里写任何路由规则,结果 404 不报错、只静默失败
为什么删了 controller 目录还提示“单应用”?
这不是缓存问题,而是 TP6 在 think\Http 构造函数里就做了硬判断:$this->multi = is_dir($this->app->getBasePath() . 'controller')。只要 app/controller 存在,哪怕它是空的、或者只是个符号链接,也会锁死为单应用。
- 正确做法不是“清缓存”或“重启服务”,而是彻底删除
app/controller 及其同级的 model、middleware、view(如果存在)
- 然后确认
config/app.php 中 'auto_multi_app' => true 已开启
- 最后检查
public/index.php 是否仍是标准启动方式(它不能被魔改,否则 Http 类可能根本没走多应用解析)
- 若仍不生效,用
var_dump($this->multi) 在 think\Http::__construct() 里打点,确认判断逻辑是否被绕过
app/ 是顶级命名空间起点,所以 app/index/ 就是 app\index\ Application 目录名首字母大写,且实际注册的自动加载前缀是 app\,但路径映射靠框架自己维护,不严格对齐 PSR-4 app/api/controller/User.php 后,必须运行 composer dump-autoload -o,否则类找不到 app\api\v1\controller\User),物理路径就必须是 app/api/v1/controller/User.php,少一层或多一层都会触发 Class not found app/index/route/app.php,不能再像 TP5 那样统一写在根目录 route/route.php 中。
- 域名绑定只在多应用模式下起作用,配置项是
app.domain_bind,写在config/app.php里 - 示例配置:
'domain_bind' => ['api.example.com' => 'api', 'admin.example.com' => 'admin']
- 注意:绑定后访问
api.example.com/user/list,TP6 才会把请求路由到app/api下的控制器;如果直接访问localhost:8000/api/user/list,仍走单应用逻辑(除非关掉app/controller并确保app.auto_multi_app = true) - 常见坑:改了
domain_bind却没清路由缓存,或没在app/api/route/app.php里写任何路由规则,结果 404 不报错、只静默失败
为什么删了 controller 目录还提示“单应用”?
这不是缓存问题,而是 TP6 在 think\Http 构造函数里就做了硬判断:$this->multi = is_dir($this->app->getBasePath() . 'controller')。只要 app/controller 存在,哪怕它是空的、或者只是个符号链接,也会锁死为单应用。
- 正确做法不是“清缓存”或“重启服务”,而是彻底删除
app/controller 及其同级的 model、middleware、view(如果存在)
- 然后确认
config/app.php 中 'auto_multi_app' => true 已开启
- 最后检查
public/index.php 是否仍是标准启动方式(它不能被魔改,否则 Http 类可能根本没走多应用解析)
- 若仍不生效,用
var_dump($this->multi) 在 think\Http::__construct() 里打点,确认判断逻辑是否被绕过
app/controller 及其同级的 model、middleware、view(如果存在) config/app.php 中 'auto_multi_app' => true 已开启 public/index.php 是否仍是标准启动方式(它不能被魔改,否则 Http 类可能根本没走多应用解析) var_dump($this->multi) 在 think\Http::__construct() 里打点,确认判断逻辑是否被绕过 TP6 的多应用不是“开个开关就行”的功能,它是一套目录结构、自动加载、路由分发、域名识别共同咬合的机制,任意一环松动,整个链条就掉链子。最常被忽略的是:删目录 ≠ 切换模式,必须让框架在启动最早期就看到“没有 controller”这个事实。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











