ThinkPHP模块需手动创建目录结构且显式配置路由。app下默认仅index模块,新增admin等模块须建对应文件夹、配置module_allow_list、在route.php声明路由,模块名须全小写无短横线,模块配置仅本模块请求生效。

模块目录结构必须手动创建,框架不自动生成
ThinkPHP 的模块化不是开箱即用的“智能划分”,app 目录下默认只有 index 模块,其他模块(比如 admin、api)得你手动建文件夹并初始化。常见错误是直接在浏览器访问 /admin 就以为模块存在了——结果 404,因为没建 app/admin/ 目录,也没配路由或模块定义。
实操建议:
- 新建模块前,先确认
app目录下已存在对应子目录,如app/admin/ - 每个模块目录里至少要有
controller/、model/、view/(可选)、config.php(可选) - 模块名必须全小写、字母数字下划线,不能含短横线(
user-center是非法模块名,会报错Invalid module name) - 若启用多应用模式(
app_multi= true),模块结构会变成app/admin/controller/Index.php;单应用模式则走app/index/controller/Index.php这种路径,别混用
模块间调用控制器不能直接 new 实例,要用 think\facade\Route 或 Url::build()
新手常把模块当普通类库,试图 new \app\admin\controller\User() 来复用逻辑——这会导致模型绑定失败、中间件不生效、请求上下文丢失。ThinkPHP 的控制器设计本就依赖容器注入和生命周期管理,裸 new 会绕过整个框架调度链。
正确做法是按场景选方式:
立即学习“PHP免费学习笔记(深入)”;
- 需要跳转到另一模块页面:用
Url::build('admin/user/index')生成 URL,再redirect() - 需要复用某模块的业务逻辑:把逻辑抽到
common/service/或app/common/下的独立类,用App::make()或依赖注入调用 - 跨模块 API 数据获取:走 HTTP 请求(
Http::get())或消息队列,别强耦合控制器 - 注意:模块间
use类路径时,命名空间必须完整,比如app\admin\model\User,漏掉app\前缀会找不到类
route.php 中模块路由必须显式声明,否则 404
即使模块目录存在,ThinkPHP 默认也不会自动注册该模块的路由。如果你访问 /admin/user/list 报 404,大概率是因为没在 route/route.php 里加规则。框架不会扫描所有子目录去“猜”哪些是模块。
典型配置方式:
- 开启模块路由支持:
'module_allow_list' => ['index', 'admin', 'api'](写在app/config/app.php) - 在
route/route.php中添加:Route::domain('admin.example.com', function () { Route::group('admin', function () { Route::get('user/list', 'admin/user/list'); }); }); - 如果用子目录部署(如
https://example.com/admin/),需额外设置'url_domain_deploy' => true并配置url_route_must防止伪静态误判 - 调试时可用
php think route:list查看当前已注册的模块级路由,确认admin是否在列表中
模块配置加载顺序容易被忽略:模块内 config.php 优先级高于全局
每个模块可放自己的 config.php(位于 app/admin/config.php),它会在全局配置之后加载,并覆盖同名键。但很多人没意识到:这个覆盖只发生在模块被实际访问时才触发——比如你从 index 模块调用 Db::name('user'),读取的仍是 index 模块的配置,不是 admin 的。
关键点:
- 模块配置只对本模块的请求生效,不会污染其他模块
- 数据库连接、缓存驱动等敏感配置若在模块 config 里改了,但忘了同步到命令行任务(如
php think hello),就会出现 Web 正常、命令行报错的情况 - 调试配置加载顺序,可在模块
config.php里临时加echo 'admin config loaded'; die;看是否执行 - 模块配置无法通过
Config::pull('database')主动拉取另一个模块的配置,只能靠统一的common/config.php或环境变量共享











