ThinkPHP中二级域名与多入口共存需分层协作:二级域名通过domain_bind实现应用级物理隔离,多入口仅用于部署级分流;二者必须分工明确,混淆将导致路由失效、配置错乱。

ThinkPHP 实现二级域名与多入口文件共存,本质不是“选一个”,而是分层协作:二级域名负责应用级物理隔离(如 admin、api 各自独立加载配置与中间件),多入口文件则用于部署级逻辑分流(如不同入口对应不同环境或调试通道)。二者不冲突,但必须明确分工——混淆会导致路由失效、控制器找不到、语言/数据库配置错乱。
先确认是否真需要多入口文件
多数场景下,所谓“多入口”其实是误用。ThinkPHP 多应用模式(app/admin/、app/api/)本身已通过子域名自动切换上下文,无需额外入口文件。只有以下情况才需真正新增入口:
- 需完全独立的启动流程,比如 admin 入口禁用某些全局中间件,而 api 入口启用 CORS 并强制 HTTPS
- 要隔离 PHP 运行时配置(如 memory_limit、opcache.enable),不同入口加载不同 php.ini
- 运维要求将不同子域名映射到不同物理路径(如 /public/admin/ 和 /public/api/),且无法统一指向同一 public 目录
若只是想让 admin.example.com 和 api.example.com 走不同模块,不需要复制 index.php,靠 domain_bind + 多应用结构即可完成。
二级域名绑定必须走 domain_bind,不是 Route::domain()
Route::domain() 只是路由层的条件分组,它不会切换应用目录、不会重设命名空间、也不会加载对应应用的 middleware.php 或 database.php。真正触发物理隔离的是 config/app.php 中的 domain_bind 配置:
立即学习“PHP免费学习笔记(深入)”;
- 写法示例:
'domain_bind' => ['admin.example.com' => 'admin', 'api.example.com' => 'api'] - 值必须是应用目录名(如 admin),该目录下要有 controller/、route/、middleware/ 等标准结构
- 绑定后,admin.example.com 的所有请求都会以 app/admin/ 为根上下文运行,控制器自动解析为
app\admin\controller\Index - 本地开发测试时,记得把
localhost:8000或127.0.0.1:8000也写进 domain_bind,否则访问失败
多入口文件如何与 domain_bind 协同工作
若确需多入口(如 admin.php、api.php),它们不能替代 domain_bind,而应作为“启动代理”:
- 每个入口文件开头需手动设置当前域名上下文,例如 admin.php 中加:
$_SERVER['HTTP_HOST'] = 'admin.example.com'; - 然后统一 require 公共入口(如 thinkphp/start.php),再由框架根据 domain_bind 自动匹配应用
- Nginx 配置中,将 admin.example.com 的 root 指向项目 public 目录,而非某个入口文件所在路径;fastcgi_param SCRIPT_FILENAME 必须指向真正的入口(如 $document_root/admin.php)
- 切勿在多个入口里重复定义 Route::domain() —— 它只应在主 route.php 中集中管理,且仅对已绑定的域名生效
Web 服务器配置的关键细节
无论是否用多入口,Nginx/Apache 必须正确传递 Host 头,否则 domain_bind 形同虚设:
- Nginx 中必须有:
fastcgi_param HTTP_HOST $host;(尤其反向代理 HTTPS 时,$host 不等于 $http_host) - server_name 必须覆盖所有二级域名,推荐用泛配:
server_name *.example.com example.com; - root 始终指向项目的
public/目录,不要指向 app/ 或某个子应用目录 - 伪静态规则必须保留 PATH_INFO,TP6+ 推荐写法:
rewrite ^(.*)$ /index.php?s=$1 last;,不能省略?s=



















