thinkphp 5 的二级域名绑定需开启 url_domain_deploy => true,通过 route::domain('m', 'mobile') 显式映射子域名到模块目录(非应用目录),绑定规则必须写在 application/route.php 中,且模块名须与 application/ 下目录名严格一致。

ThinkPHP 5 的二级域名绑定不是“自动识别应用”,而是靠 Route::domain() 显式把子域名映射到模块(module),它不支持 TP6 那种真正的多应用(app/xxx/ 目录结构)。如果你在绑定了 m.example.com 后访问 404,大概率是模块名写错、路由没生效,或没开关键配置。
必须开启 url_domain_deploy
这是整个机制的开关,不启用就完全不解析 Host。在 application/config.php 中确认这一行存在且为 true:
'url_domain_deploy' => true,
注意:APP_SUB_DOMAIN_DEPLOY 是 TP3/TP5.0 的旧配置,TP5.1+ 已废弃,写了也无效。本地测试时别忘了改 hosts 文件,比如加两行:
127.0.0.1 example.com<br>127.0.0.1 m.example.com
Route::domain() 绑定的是模块名,不是目录名
TP5 没有 “app/admin/” 这种应用目录概念,只有 application/mobile/ 这样的模块目录。你写的第二个参数必须和 application/ 下的模块目录名严格一致(大小写敏感):
-
Route::domain('m', 'mobile');→ 正确,前提是存在application/mobile/ -
Route::domain('api', 'api');→ 错误,除非你真建了application/api/模块;如果只是想走application/index/controller/Api.php,那就不能用 domain 绑定,得走普通路由 - 模块下必须有
controller/和view/,且控制器命名要符合 TP5 规范(如Index类对应index方法)
子域名路由规则必须注册在 application/route.php 中
TP5 不支持按域名拆分路由文件,所有 Route::domain() 必须写在主路由文件里,且要在 return []; 之前。常见错误写法:
- 写在某个控制器里 —— 不执行
- 写在
application/common.php—— 加载时机太晚,路由已初始化 - 写在
route/子目录下其他文件且没被引入 —— 完全不加载
正确结构示例:
<?php <br>use think\Route;<br>Route::domain('m', 'mobile');<br>Route::domain('admin', 'admin');<br><br>return [<br> '__domain__' => [<br> 'm' => 'mobile',<br> 'admin' => 'admin'<br> ]<br>];
访问 m.example.com 却提示“控制器不存在”的原因
这通常不是路由没绑对,而是模块内控制器路径或命名出问题:
- 模块目录名是
mobile,但控制器类名写成了MobileController—— TP5 默认找Index控制器,不是模块名拼接的类名 - URL 访问的是
m.example.com/,但mobile/controller/Index.php里没有index()方法 - 模块下的
config.php里设置了'default_controller' => 'Home',但没提供Home.php控制器 - 开启了强制路由(
url_route_must),但模块内没定义任何路由规则,导致根路径 404
最简单的验证方式:直接访问 m.example.com/index/index,看是否能进 mobile/controller/Index.php 的 index() 方法。如果能,说明绑定成功,问题出在默认路由或模块配置上。
TP5 的二级域名绑定本质是“模块路由代理”,它不隔离配置、中间件或数据库连接。如果你需要真正独立的应用上下文(比如不同数据库、不同中间件栈),TP5 做不到,得升到 TP6 + think-multi-app,或者用 Nginx 分流到多个独立入口文件。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











