Laravel中怎么配置多域名访问_Laravel 域名路由匹配技巧【方案】

1次阅读

laravel 需用 Route::domain() 显式配置域名路由,仅对内部路由生效;子域名支持通配符如 {sub}.example.com;多域名共享控制器时应在全局中间件解析 Host 并绑定租户上下文;失效主因是 http_HOST 头未正确透传。

Laravel中怎么配置多域名访问_Laravel 域名路由匹配技巧【方案】

怎么让 Laravel 路由匹配不同域名

Laravel 本身不自动根据域名区分路由,必须显式配置域名约束,否则所有域名都会命中同一组路由。关键在 Route::domain() 的使用时机和作用域——它只对内部定义的路由生效,且不能嵌套在 Route::group() 的普通 middlewareprefix 分组里混用。

常见错误是把域名逻辑写在中间件里做跳转或重定向,这属于运行时判断,既低效又绕过路由缓存,还容易导致 https/HTTP 协议不一致问题。

  • 每个需要独立域名逻辑的路由组,必须用 Route::domain('xxx.com') 包裹
  • 子域名支持用通配符:如 Route::domain('{sub}.example.com'),对应路由中需声明 $sub 参数
  • 本地开发时,127.0.0.1localhost 是两个不同域名,需分别配置或统一 hosts 绑定
  • 部署到 nginx/apache 时,确保 Web 服务器已将请求的原始 Host 头透传给 php(Laravel 依赖它做匹配)

Laravel 多域名共享同一套控制器但隔离数据怎么办

典型场景:SaaS 系统中多个客户子域名(如 client1.app.comclient2.app.com)共用 HomeController@index,但要加载各自租户数据。这时不能靠路由参数传递租户 ID,而应在中间件中解析域名并绑定上下文。

推荐做法是在全局中间件(如 AppHttpMiddlewareResolveTenant)里读取 request()->getHost(),查出对应租户,再塞进 Laravel 容器或请求属性中。后续控制器可直接通过 $request->tenantapp('tenant') 获取。

  • 不要在控制器构造函数里解析域名——路由尚未完全解析完成,$request->getHost() 可能不可靠
  • 避免在模型作用域(Scopes)里重复查租户,应提前解析并缓存到请求生命周期内
  • 若使用多数据库连接,域名解析后应动态切换 DB::connection(),而不是硬编码连接名

为什么 Route::domain() 不生效?常见环境陷阱

最常踩的坑不是代码写错,而是环境没对齐。Laravel 的域名匹配完全依赖 $_SERVER['HTTP_HOST'],而这个值极易被反向代理、负载均衡或本地 hosts 设置干扰。

  • docker 环境中,Nginx 容器未设置 proxy_set_header Host $host;$_SERVER['HTTP_HOST'] 变成上游 IP 或空
  • Cloudflare 代理下,默认屏蔽真实 Host 头,需开启「Preserve original host header」或改用 CF-Connecting-IP + 自定义规则
  • Homestead/Valet 下,如果没在 /etc/hosts 中为每个测试域名添加映射(如 127.0.0.1 site1.test site2.test),浏览器根本不会发对应 Host 头
  • Artisan 命令行执行路由列表(php artisan route:list)不显示 domain 列——它只反映当前 CLI 请求的 Host,不代表实际 Web 请求行为

要不要用 RouteServiceProvider 动态加载域名路由文件

可以,但没必要过度设计。简单项目直接在 routes/web.php 里分块写 Route::domain() 更清晰;复杂 SaaS 项目才值得拆出 routes/domains/ 目录,配合 RouteServiceProvider::loadDomainRoutes() 按需加载。

注意:动态加载本质还是 PHP 文件包含,不会带来性能优势;反而增加调试难度——IDE 可能无法跳转,route:list 输出也不直观。真正影响性能的是路由编译缓存是否启用(php artisan route:cache),而它要求所有路由定义必须是静态可分析的,动态 require 会直接报错。

  • 若用了 route:cache,就别在路由文件里写条件判断或函数调用,包括 env()config()
  • 域名路由一旦缓存,修改后必须重新执行 php artisan route:cache,否则新域名不会生效
  • 测试环境建议关掉路由缓存,避免本地改了路由却一直走旧缓存

域名路由的核心其实是 Host 头的可信传递和早期解析——后面所有逻辑都建立在这个基础上。很多人花时间调路由写法,最后发现是 Nginx 没透传头,或者本地 dns 解析绕过了 hosts。

text=ZqhQzanResources