TP6推荐“多应用”而非“多模块”实现模块化,每个功能域为独立应用,具备物理隔离、独立配置与路由隔离特性。

ThinkPHP 的 MVC 架构本身不强制模块化,但大型项目必须通过合理分层来支撑可维护性。TP6 官方已明确将传统「多模块」(APP_MULTI_MODULE = true)列为历史兼容特性,不再推荐用于新项目。真正可持续的模块化路径是「单模块 + 多应用」或「领域分层 + 命名空间隔离」,核心在于物理隔离、职责收敛与加载可控。
多应用才是 TP6 推荐的模块化主干
所谓“多模块”在 TP6 中实际应理解为“多应用”——每个功能域(如后台 admin、API 接口 api、移动端 mobile)都是平级的独立应用,而非子目录嵌套的模块:
- 用
php think build:app admin命令创建,生成完整结构:app/admin/controller/、app/admin/route/app.php、app/admin/config/ 等 - 各应用拥有独立生命周期,可单独配置数据库连接、中间件栈、事件监听器
- 路由完全隔离:app/admin/route/app.php 中定义的规则,不会与 app/api/route/app.php 冲突
- 命令行需显式指定作用域,例如
php think migrate:run --app=admin
共享逻辑必须走 PSR-4 或 Composer,禁用跨应用 include
TP6 已移除 app/common 全局目录,任何试图通过相对路径引入其他应用代码的做法都会破坏自动加载机制:
- 通用服务(如支付客户端、短信网关)应封装为独立 Composer 包,通过
composer require mycorp/payment引入 - 暂不发包时,在
app/同级建src/目录,配置composer.json的 autoload:"autoload": { "psr-4": { "Shared\": "src/" } } - 在控制器中直接
use Shared\PaymentClient;调用,IDE 可跳转、类加载稳定 - 绝对禁止在 app/admin/controller/ 中写
require '../../api/service/Payment.php'—— 类找不到、调试困难、部署失败
路由与中间件必须按应用边界收敛
模块化失效最常见的原因是路由和中间件越界使用:
立即学习“PHP免费学习笔记(深入)”;
- 全局
config/route.php中必须显式导入各应用路由:Route::import('admin', 'admin');漏掉即 404 - 每个应用的路由文件(如 app/admin/route/app.php)只注册本应用相关接口,不依赖 prefix 或 domain 自动识别
- 中间件类按应用命名空间存放,例如
appdminmiddlewareAuth和apppimiddlewareJwtAuth必须分离 - 不同应用即使功能相似(如鉴权),也应各自实现——后台用 session+guard,API 用 JWT,混用会导致 guard 切换错乱、token 校验失效
目录结构与命名必须严格对齐 PSR-4
物理路径、命名空间、类名三者一致,是自动加载不出错的基础:
- 应用目录名全小写、仅含字母与下划线:
app/admin✅,app/Admin❌,app/user-v2❌ - 控制器类名以
Controller结尾,首字母大写驼峰:IndexController.php→appdmincontrollerIndexController - 服务类统一放
app/service/(非模块内),以Service结尾:UserRegisterService.php - 模型保持纯粹,只处理数据映射与基础验证;复杂流程(如注册+发短信+写日志)交由服务层编排



















