ThinkPHP域名绑定需在根目录route/route.php中用Route::domain()定义,不能放模块路由文件;多模块同域名时需关闭auto_multi_module并手动绑定路径前缀;URL生成须显式传domain参数;Web服务器须配置泛域名支持。

ThinkPHP 多模块下 domain_bind 不生效?检查路由分组绑定位置
域名绑定必须写在「全局路由定义」里,不能放在某个模块的 route.php 中——模块级路由文件只对本模块生效,而域名绑定是入口层的分流动作,早于模块解析。
常见错误现象:domain_bind 配置写了但访问时仍进错模块,或直接 404;php think route:list 查不到对应域名路由规则。
- 正确位置:项目根目录
route/route.php(非app/index/route.php) - 绑定语法用
Route::domain()分组,不是Route::rule() - 子域名绑定后,内部路由需用
group或闭包定义,否则不继承域名上下文
Route::domain('admin.example.com', function () {
Route::get('index', 'admin/Index/index');
});
多模块共用同一二级域名时,如何靠路径前缀区分?
当多个模块(如 admin、api、shop)都部署在 example.com 下,不能靠域名区分,就得用 URL 路径前缀 + 模块映射。
关键点在于关闭自动多模块识别,改用显式路由重写,避免 example.com/admin/xxx 被误判为「模块名 admin」再套一层模块解析。
立即学习“PHP免费学习笔记(深入)”;
- 在
config/app.php中设'auto_multi_module' => false - 手动在
route/route.php中绑定路径前缀到对应模块控制器:Route::get('admin/:all', 'admin@:all')->ext('html') - 注意
ext设置要匹配实际访问后缀,否则伪静态规则可能失效
Url::build() 生成链接时域名丢失?补全 domain 参数
默认 Url::build() 只拼路径,不会自动带绑定的域名;跨模块跳转时容易生成相对路径,导致前端请求发到当前域名而非目标模块域名。
这不是 bug,是设计使然——URL 生成器不感知路由绑定关系,只认当前请求上下文或显式传参。
- 生成跨域名链接时,必须显式传
['domain' => 'admin.example.com'] - 别依赖
Request::domain(),它返回的是当前请求的域名,不是目标模块域名 - 如果大量使用,建议封装一个
admin_url()辅助函数,内部固定domain参数
Url::build('admin/Index/index', [], true, ['domain' => 'admin.example.com'])
Apache/Nginx 配置没做泛域名支持,*.example.com 绑定会失败
ThinkPHP 的域名绑定只是 PHP 层路由逻辑,前提是 Web 服务器已把请求正确转发过来。如果 Nginx 没配 server_name *.example.com,或者 Apache 的 VirtualHost 缺少对应 ServerAlias,那请求根本到不了 PHP。
典型表现:浏览器访问 admin.example.com 直接 404 或跳到默认站点,$_SERVER['HTTP_HOST'] 打印出来是空或错的。
- Nginx 必须加
server_name example.com *.example.com;,不能只写主域名 - 本地开发用 hosts 绑定多个子域名时,确保每个都指向 127.0.0.1,且无缓存干扰
- HTTPS 场景下,泛域名证书必须已部署,否则浏览器会拦截连接,压根不发请求


















