thinkphp 6 的 _domain 方法不支持泛域名通配符,仅接受具体域名字符串或数组;配置 *.example.com 不报错但完全不匹配,因底层为严格字符串比对而非正则解析。

ThinkPHP 6 的 _domain 路由方法不支持泛域名通配符
直接说结论:_domain 方法在 ThinkPHP 6 中只接受具体域名字符串或数组,**无法识别 *.example.com 这类通配符写法**。你写进去也不会报错,但路由完全不匹配——因为底层用的是严格字符串比对或 in_array 判断,不是正则或通配符解析。
常见错误现象是:配置了 Route::domain('*.example.com', [...]),结果所有子域名请求都 fallback 到默认路由,_domain 分组内定义的规则一条都不生效。
- 真正能用的只有精确域名(如
'admin.example.com')或域名列表(如['api.example.com', 'pay.example.com']) - 如果想让
user1.example.com、user2.example.com都走同一组路由,必须换思路——不能依赖_domain的“声明式”绑定 - TP6 的
Route::domain()底层调用的是think\Route::bindDomain(),该方法压根没做通配符展开逻辑
用中间件 + Request::host() 提取子域名并动态绑定模块
泛域名路由的本质是「根据 Host 头动态决定模块/控制器」,不是靠路由注册时静态写死。ThinkPHP 没提供开箱即用的泛域名支持,就得自己在请求生命周期早期介入。
推荐做法:写一个全局中间件,在路由解析前从 Request::host() 中提取子域名,然后手动设置 module 参数,让后续路由和调度按需走对应模块。
- 中间件里用
strtok($request->host(), '.') ?: ''取第一段(注意要过滤 www 和主域名) - 别直接改
$request->param('module'),应调用$request->setModule($moduleName)确保被框架识别 - 确保中间件执行顺序早于
think\middleware\ParseUrl(即路由解析中间件),否则 module 已被固定 - 模块目录结构得提前建好,比如
app/user1/、app/user2/,否则会提示模块不存在
示例中间件片段:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
public function handle($request, \Closure $next)
{
$host = $request->host();
$sub = strtok($host, '.');
if ($sub && $sub !== 'www' && $sub !== 'example') {
$request->setModule($sub);
}
return $next($request);
}
route.php 里别再试图用 domain 绑定泛域名模块
很多人卡在这一步:反复修改 Route::domain('* .example.com', ...) 或 Route::domain('{sub}.example.com', ...),以为只是语法不对。其实 TP6 的路由文件根本不支持这种占位符写法——domain 方法第二个参数只接受闭包或数组,第一个参数只认死字符串。
如果你硬要在这里“模拟”,比如写成 Route::domain('user1.example.com|user2.example.com', [...]),那等于手动维护白名单,失去泛域名意义,还容易漏配、难维护。
- 所有带
*、{xxx}、正则表达式的 domain 写法,在 TP6 中都会被当字面量处理,不会触发匹配逻辑 - 即使配合
Route::pattern()也无效,因为 pattern 只作用于路由变量,不作用于 domain 字段 - 别指望
config('app.domain_bind')能救场,它只控制单个应用的域名绑定,且不支持通配符
注意子域名与 HTTPS、Cookie 域名的兼容性影响
泛域名路由跑通后,容易忽略配套的基础设施问题。比如用户登录态跨子域名失效、静态资源 404、HTTPS 证书不覆盖等,这些不是框架问题,但会让人误以为路由没生效。
- Session Cookie 的
domain必须设为.example.com(开头带点),否则user1.example.com登录后,user2.example.com读不到 session - Nginx/Apache 需确认已正确转发
Host头,Docker 或反向代理场景下常被覆盖成localhost - Let’s Encrypt 的泛域名证书需要 DNS-01 验证,且证书中必须明确包含
*.example.com,光有example.com不行 - 前端发请求时若用相对路径,可能因当前页面 host 是
user1.example.com导致 API 请求发到同子域名下,而你的 API 其实部署在api.example.com
泛域名真正的复杂点不在路由怎么写,而在整个请求链路上的域名一致性——从 DNS、TLS、反向代理、框架路由,到浏览器 Cookie 和前端请求地址,缺一不可。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










