Route::domain() 是以子域名作为路由分组触发条件的机制,必须写在 route/app.php 中,仅支持完整域名绑定或带 pattern 限制的变量通配(如 '{sub}.example.com'),不支持裸通配符,不可嵌套,多域名可复用同一闭包。

ThinkPHP 的 Route::domain() 不是简单“加个子域名”,而是以域名作为路由分组的触发开关,用对了能自然隔离业务、复用逻辑、避免硬编码。关键在写对位置、配对配置、理解匹配逻辑。
必须写在 route/app.php 里,其他地方全无效
它只在框架初始化路由阶段扫描一次,仅 route/app.php(或旧版 app/common/route.php)中调用才生效。写在中间件、控制器、config/route.php 或各应用自己的 route.php 中,请求进来时根本不会识别。
- 多应用项目也统一写在根目录的
route/app.php,不要拆到app/admin/route.php等位置 - 若用了
domain_bind.php配置,那是应用层绑定,和Route::domain()的路由层过滤不冲突,但作用不同 - 本地调试时注意:浏览器访问
localhost:8000,HTTP_HOST就是localhost:8000,规则得写成Route::domain('localhost:8000', ...)
支持显式绑定与变量通配,但写法很严格
TP6 不支持 Route::domain('*') 或 Route::domain('{sub}') 这类裸通配写法,会直接报错。正确方式只有两种:
- 完整域名绑定:
Route::domain('admin.example.com', 'admin')—— 精确匹配,推荐用于生产环境 - 变量通配绑定:
Route::domain('{sub}.example.com', function ($sub) { ... })—— 必须配合->pattern(['sub' => '\w+'])限制变量格式,防止空值或非法字符注入
变量 $sub 会自动注入闭包,也可在控制器方法签名中接收,比如 public function index($sub) { }。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
立即学习“PHP免费学习笔记(深入)”;
多个子域名共用一套路由?别重复写,用变量引用
想让 admin.example.com 和 shop.example.com 都有相同的用户管理接口,不用复制两遍路由定义:
- 先把公共路由抽成闭包变量:
$userRoutes = function () { Route::get('user/:id', 'User/read'); }; - 再分别绑定:
Route::domain('admin.example.com', $userRoutes);和Route::domain('shop.example.com', $userRoutes); - 某域名需要额外接口?在闭包里追加:
Route::domain('api.example.com', function () use ($userRoutes) { $userRoutes(); Route::post('login', 'Auth/login'); });
可以嵌套 Route::group,但顺序不能反
Route::domain() 是最外层分组条件,内部可自由使用 Route::group() 做前缀或命名空间管理:
- ✅ 正确:
Route::domain('admin.example.com', function () { Route::group('v1', function () { Route::get('user', 'User/index'); }); }); - ❌ 错误:把
Route::group()写在外面,再在里面写Route::domain()—— 完全不生效 - 闭包内还可调用
require引入独立文件,比如require __DIR__ . '/admin_routes.php';,适合路由量大的场景


















