ThinkPHP泛域名路由需用Route::domain('*')显式声明并配合Nginx通配符server_name、hosts多行配置及手动解析subDomain(),否则子域名无法匹配。

泛域名路由怎么写才不匹配不到子域名
ThinkPHP 的泛域名路由必须用 domain 规则显式声明,不能只靠 route.php 里的普通规则“猜”。默认情况下,http://a.example.com 和 http://b.example.com 都不会自动进入你写的 Route::get('index', ...),除非你明确告诉框架:“这些子域名归我管”。
- 在
route/route.php中,用Route::domain('*') → group(...)包裹需要泛匹配的路由 - 必须配合
Request::domain()或Request::subDomain()手动提取子域名,框架不会自动注入到参数里 - 如果用了 Nginx,确保
server_name包含通配符(如*.example.com),否则请求根本进不到 PHP 层 -
Route::domain('*.example.com')写法无效 —— ThinkPHP 不支持带点的通配符写法,只能写'*'
如何让不同子域名走不同模块或控制器
泛域名本身不等于自动分发,你需要在路由分组里手动做判断,再重定向或绑定到对应模块。直接靠配置文件“绑定子域名到模块”在 ThinkPHP 6+ 已被移除,硬编码判断是唯一可靠方式。
- 在
Route::domain('*') → group(...)里,先调用request()->subDomain()拿子域名字符串 - 用
switch或match映射子域名到模块名,例如'shop' → 'app\shop\controller\Index' - 避免在路由闭包里写太多逻辑,建议封装成一个
SubDomainDispatcher类,统一处理解析和转发 - 注意:子域名为空(即访问主域名)时
subDomain()返回空字符串,不是null,别用=== null判断
为什么本地开发时泛域名老是 404
绝大多数情况不是 ThinkPHP 配置问题,而是本地 HTTP 服务没把请求正确传给它。特别是用内置服务器(php think run)或 Apache 时,泛域名根本不会被识别。
- 内置服务器不支持 Host 头匹配,
php -S默认无视Host,所以a.example.com和b.example.com全部当作localhost处理 - Apache 需开启
vhost_alias模块,并在虚拟主机配置中写ServerAlias *.example.com - Nginx 最稳妥:用
server_name _;或server_name *.example.com;,并确认listen 80;没被其他 server 块抢占 - hosts 文件要加多行,比如:
127.0.0.1 a.example.com、127.0.0.1 b.example.com,不能只写*.example.com
泛域名 + HTTPS 下 subDomain() 取不到值怎么办
HTTPS 环境下,某些反向代理(如 Nginx + SSL 终止)会丢失原始 Host 头,导致 Request::subDomain() 解析失败,返回空或错误值。
立即学习“PHP免费学习笔记(深入)”;
- 检查 Nginx 配置里是否设置了
proxy_set_header Host $host;,漏掉这句就会丢 Host - 如果用了 CDN 或 WAF(如 Cloudflare),确认它没有强制改写 Host 头;部分服务会把 Host 改成源站域名
- 临时调试可用
$_SERVER['HTTP_HOST']直接取值,但要注意端口(如example.com:443),需用parse_url()或正则剥离 - ThinkPHP 的
subDomain()默认基于HTTP_HOST,但受app.domain_bind和app.url_domain_deploy配置影响,这两个设为false可避免干扰
route.php,而在 Nginx 的 server_name 没生效,或者本地 hosts 忘了加具体子域名条目。


















