ThinkPHP通过域名识别+应用级绑定实现index、admin、api三模块二级域名独立访问:需启用多应用结构、配置domain_bind映射完整域名到对应应用目录,并确保Web服务器正确传递Host头。

ThinkPHP 实现 index、admin、api 三个模块通过二级域名(如 www.example.com、admin.example.com、api.example.com)独立访问,核心不是改入口文件或复制多套代码,而是靠域名识别 + 应用级绑定。关键在两层配置:Web 服务器正确传入 Host 头,框架精准分发到对应应用目录。
一、确保项目是多应用结构
这是前提,否则子域名无法加载独立模块:
- 已执行
composer require topthink/think-multi-app - 根目录下
app/controller/目录已被删除(触发多应用模式) - 已用命令创建三个应用:
php think build index、php think build admin、php think build api,生成app/index/、app/admin/、app/api/目录 - 每个应用内含独立的
controller/、route.php和middleware.php
二、启用域名部署并绑定完整域名
仅靠 Route::domain() 不够——它只影响路由解析,不能切换应用上下文。必须配置 domain_bind,让框架启动时就加载对应应用:
- 编辑
config/app.php,添加或确认以下配置:
return [
'url_domain_deploy' => true,
'domain_bind' => [
'www.example.com' => 'index',
'example.com' => 'index',
'admin.example.com' => 'admin',
'api.example.com' => 'api',
],
];
```
-
domain_bind键必须是完整域名(不含协议、路径),值为app/下的目录名 - 绑定后,控制器命名空间自动变为
index\controller\、admin\controller\等,视图路径、配置、中间件也按对应应用加载 - 若开发环境用
localhost或带端口(如localhost:8080),键名需写全,且 Web 服务器要转发该请求
三、Web 服务器必须传递正确的 Host 头
ThinkPHP 的 Request::domain() 完全依赖 $_SERVER['HTTP_HOST']。Nginx/Apache 配置错误会导致所有请求 fallback 到默认应用:
立即学习“PHP免费学习笔记(深入)”;
- Nginx 示例(server 块):
server_name www.example.com example.com admin.example.com api.example.com;
root /path/to/your/project/public;
index index.php;
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
}
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_HOST $host;
include fastcgi_params;
}
```
- 务必包含所有目标域名在
server_name中,或使用泛匹配(如~^(?<sub>.+)\.example\.com$</sub>) - 确保
fastcgi_param HTTP_HOST $host;存在且未被覆盖 - Apache 用户需开启
mod_rewrite,并在.htaccess中启用RewriteEngine On,同时设置AllowOverride All
四、可选:补充子域名路由细化控制
domain_bind 已完成应用级隔离,但你仍可在各应用内部用 Route::domain() 做路径级优化(非必需):
- 例如在
app/admin/route.php中定义:
use think\Route;
Route::domain('admin.example.com', function () {
Route::get('login', 'index/login');
Route::get('dashboard', 'index/dashboard');
});
```
- 注意:这个闭包只对已绑定到
admin应用的admin.example.com请求生效 - 不要在
route/app.php中为未声明在domain_bind的域名调用Route::domain(),它不会起作用



















