Laravel 需用 Route::domain() 显式配置域名路由,仅对内部路由生效;子域名支持通配符如 {sub}.example.com;多域名共享控制器时应在全局中间件解析 Host 并绑定租户上下文;失效主因是 HTTP_HOST 头未正确透传。
怎么让 Laravel 路由匹配不同域名
Laravel 本身不自动根据域名区分路由,必须显式配置域名约束,否则所有域名都会命中同一组路由。关键在 Route::domain() 的使用时机和作用域——它只对内部定义的路由生效,且不能嵌套在 Route::group() 的普通 middleware 或 prefix 分组里混用。
常见错误是把域名逻辑写在中间件里做跳转或重定向,这属于运行时判断,既低效又绕过路由缓存,还容易导致 HTTPS/HTTP 协议不一致问题。
- 每个需要独立域名逻辑的路由组,必须用
Route::domain('xxx.com')包裹 - 子域名支持用通配符:如
Route::domain('{sub}.example.com'),对应路由中需声明$sub参数 - 本地开发时,
127.0.0.1和localhost是两个不同域名,需分别配置或统一 hosts 绑定 - 部署到 Nginx/Apache 时,确保 Web 服务器已将请求的原始
Host头透传给 PHP(Laravel 依赖它做匹配)
Laravel 多域名共享同一套控制器但隔离数据怎么办
典型场景:SaaS 系统中多个客户子域名(如 client1.app.com、client2.app.com)共用 HomeController@index,但要加载各自租户数据。这时不能靠路由参数传递租户 ID,而应在中间件中解析域名并绑定上下文。
推荐做法是在全局中间件(如 App\Http\Middleware\ResolveTenant)里读取 request()->getHost(),查出对应租户,再塞进 Laravel 容器或请求属性中。后续控制器可直接通过 $request->tenant 或 app('tenant') 获取。
- 不要在控制器构造函数里解析域名——路由尚未完全解析完成,
$request->getHost()可能不可靠 - 避免在模型作用域(Scopes)里重复查租户,应提前解析并缓存到请求生命周期内
- 若使用多数据库连接,域名解析后应动态切换
DB::connection(),而不是硬编码连接名
为什么 Route::domain() 不生效?常见环境陷阱
最常踩的坑不是代码写错,而是环境没对齐。Laravel 的域名匹配完全依赖 $_SERVER['HTTP_HOST'],而这个值极易被反向代理、负载均衡或本地 hosts 设置干扰。