子域名路由必须用 Route::domain() 而非 Route::prefix(),需在 RouteServiceProvider 的 mapWebRoutes() 中定义,配合泛解析 DNS、/etc/hosts 配置、中间件动态切换数据库及 SESSION_DOMAIN=.example.com 设置 Cookie 域名。

子域名路由必须用 Route::domain() 而不是 Route::prefix()
很多人误以为子域名是“路径前缀”,试图用 Route::prefix('shop.example.com') 或拼接字符串方式处理,这完全无效。Laravel 的子域名识别依赖 HTTP Host 头解析,只有 Route::domain() 会启用 Host 匹配逻辑,且必须在 RouteServiceProvider 的 mapWebRoutes() 阶段注册(即在 routes/web.php 中不可直接用)。
实操建议:
- 在
app/Providers/RouteServiceProvider.php的mapWebRoutes()方法内,用Route::domain('{tenant}.example.com')定义子域名路由组 -
{tenant}是占位符变量,会自动注入到控制器方法或中间件中,类型为 string - 确保 Web 服务器(Nginx/Apache)已配置泛解析,例如 Nginx 的
server_name *.example.com;,否则请求根本不会到达 Laravel - 本地开发时,需在
/etc/hosts添加多条记录,如:127.0.0.1 tenant1.example.com、127.0.0.1 tenant2.example.com
如何从子域名提取租户并切换数据库连接
单纯匹配子域名只是第一步,关键是要根据 {tenant} 动态加载对应租户的数据库配置。不能在路由闭包里硬编码 DB::connection() 切换,容易引发连接复用和事务异常。
实操建议:
- 在全局中间件(如
App\Http\Middleware\InitializeTenant)中,通过$request->route('tenant')获取子域名值 - 查表(如
tenants表)验证该租户是否存在且状态为 active,失败则返回 404 或重定向 - 调用
Config::set('database.connections.tenant.database', $tenantDbName)临时覆盖连接配置,再执行DB::purge('tenant')强制重建连接 - 避免在模型中使用
protected $connection = 'tenant'静态绑定,而应在每个请求生命周期开始时动态设置,默认连接保持为mysql(主库)
Route::domain() 和 Route::middleware() 的执行顺序陷阱
中间件在路由匹配之后才执行,但子域名参数 {tenant} 必须在中间件运行前就可用——这点常被忽略,导致中间件里取不到 $request->route('tenant')。
常见错误现象:中间件中 $request->route('tenant') 返回 null,或报错 “Undefined array key 'tenant'”。
原因与解决:
- 错误写法:把
Route::domain(...)->middleware(...)写在routes/web.php—— 此处不支持 domain 路由定义 - 正确位置:只能在
RouteServiceProvider::mapWebRoutes()中,且Route::domain()必须包裹整个路由组,中间件需作为第二个参数传入group(),例如:Route::domain('{tenant}.example.com')->group(function () { Route::get('/dashboard', [DashboardController::class, 'index']); }, ['middleware' => 'tenant.init']); - 确保中间件类已注册到
app/Http/Kernel.php的$middlewareGroups['web']或$routeMiddleware中
HTTPS + 子域名下 Cookie 域名不生效的问题
启用 HTTPS 后,若未显式设置 Cookie 域名,Laravel 默认只在当前完整 Host 下发送 Cookie(如 tenant1.example.com),导致跨子域名登录态无法共享,也无法在主站 example.com 设置通用 session。
实操建议:
子域名路由本身不复杂,真正卡住人的永远是 Web 服务器配置、Cookie 域名、数据库连接隔离这三个环节。漏掉任意一个,都会表现为“路由能进,但数据不对”或“登录后跳回主站”。










