ThinkPHP5的域名部署功能必须设置'url_domain_deploy'=>true才生效,否则Route::domain()调用将被忽略;该配置为布尔值,不可写成字符串或数字,且TP5.0/5.1/5.2均适用此规则。

ThinkPHP5 的 url_domain_deploy 必须设为 true 才生效
域名部署功能在 TP5 中默认关闭,不手动开启就完全不会走域名匹配逻辑。很多人写了 Route::domain() 却没效果,根本原因就是漏了这一步。
必须在 application/config.php(或对应环境配置文件)中显式设置:
return [
// ...
'url_domain_deploy' => true,
// ...
];
注意:url_domain_deploy 是布尔值,不是字符串;写成 'url_domain_deploy' => 'true' 或 1 都无效。
- 该配置只控制「域名部署」机制是否启用,和路由定义位置无关
- 一旦设为
false或未定义,所有Route::domain()调用都会被忽略 - TP5.0/5.1/5.2 均适用此规则,无版本差异
Route::domain() 的第二个参数不能是字符串路径
常见错误是直接传控制器方法字符串,比如 Route::domain('m', 'mobile/index/index') —— 这会报错 Invalid route rule,因为 TP5 的 Route::domain() 不接受字符串作为路由目标。
它只接受两种形式:
- 模块名(字符串):如
Route::domain('m', 'mobile')→ 绑定到mobile模块,后续 URL 自动补前缀 - 闭包或数组:用于定义子域名下的完整路由规则集,例如:
Route::domain('api', function () {
Route::get('v1/user', 'api/v1.User/get');
});
如果想复用已有模块结构又不想写闭包,推荐用模块绑定方式,而非强行塞路径字符串。
本地开发时 url_domain_root 很可能要手动配
TP5 默认尝试自动提取根域名,但遇到 com.cn、net.cn 或三级域名(如 dev.api.example.com)时极易失败,导致子域名匹配不上。
解决办法是在 config.php 显式指定:
'url_domain_root' => 'example.com.cn',
这个值必须和你 hosts 里写的主域名后缀严格一致。比如 hosts 写了:
127.0.0.1 m.example.com.cn
那 url_domain_root 就得填 example.com.cn,填 com.cn 或 example.com 都不行。
- 不配
url_domain_root时,TP5 用strrchr($_SERVER['HTTP_HOST'], '.')截取,对多级后缀不可靠 - 配错会导致
m.example.com.cn被识别成com.cn,子域名m就丢了 - 生产环境也建议配,避免 DNS 解析差异引发的隐性问题
hosts + Apache/Nginx 配置只是辅助,TP5 域名匹配不依赖它们
很多人花几小时调 Apache 虚拟主机或 Nginx server_name,结果发现 TP5 还是不认子域名——因为框架层的域名匹配只看 $_SERVER['HTTP_HOST'],只要这个值对了,框架就能工作。
所以本地验证只需两步:
- 改
C:\Windows\System32\drivers\etc\hosts,加一行:127.0.0.1 m.example.com - 浏览器访问
http://m.example.com:8000(端口必须和你启动的服务一致)
不需要 Apache 配 VirtualHost,也不需要 Nginx server_name —— TP5 在 PHP 层就完成了路由分发。唯一例外是 HTTPS 场景,此时 $_SERVER['HTTP_HOST'] 可能被代理覆盖,需检查反向代理头设置。
真正容易被忽略的是:开发服务器端口必须和 HTTP_HOST 中出现的端口一致。比如你用 php think run -p 8080,那 hosts 对应的域名就必须带 :8080 访问,否则匹配失败。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











