Laravel子域名路由需Web服务器正确转发请求并配置domain分组,Nginx/Apache须支持通配符域名,/etc/hosts需添加对应条目,路由须用Route::domain()定义,注意Cookie共享需设置session.domain为'.example.com'。

Laravel 本身支持子域名路由,但二级域名(如 admin.example.com、api.example.com)不是开箱即用的“自动识别”,关键在于 Web 服务器是否将请求正确转发到 Laravel,并且 Laravel 是否在路由定义中启用子域名分组。
Web 服务器必须把所有子域名指向同一 Laravel 入口
这是最容易被忽略的前提。Laravel 不会自己监听 admin.example.com,它只接收已由 Nginx/Apache 转发过来的请求。
常见错误现象:admin.example.com 打开是 404 或直接显示 Nginx 欢迎页 —— 这说明请求根本没进 Laravel。
- Nginx 配置中,
server_name必须包含通配符或显式列出子域名,例如:server_name example.com *.example.com; - Apache 需启用
vhost_alias模块,并在VirtualHost中用ServerAlias *.example.com - 本地开发时,
/etc/hosts要加多行,比如:127.0.0.1 example.com
127.0.0.1 admin.example.com
127.0.0.1 api.example.com
Laravel 路由文件中用 domain 方法声明子域名分组
子域名路由必须用 Route::domain() 包裹,不能只靠 Route::prefix() 或中间件模拟。
参数差异:domain 接收字符串,支持通配符 {sub} 占位符,用于捕获子域名段;但注意:Laravel 5.5+ 才支持在 domain 中使用带花括号的动态段。
典型写法:
Route::domain('{sub}.example.com')->group(function () {
Route::get('/users', function ($sub) {
return "This is {$sub}'s area";
});
});
如果只匹配固定二级域名(如仅 admin.example.com),直接写死更安全:
Route::domain('admin.example.com')->group(function () {
Route::get('/', [AdminController::class, 'index']);
});
注意:{sub} 是路由参数,必须出现在闭包函数签名或控制器方法参数中才能被注入。
子域名路由与 HTTPS、Cookie、Session 的兼容性问题
二级域名下默认无法共享 Cookie,这会导致登录态丢失、Session 不同步等现象 —— 这不是 Laravel bug,而是浏览器同源策略限制。
解决方案取决于部署方式:
- 若使用 HTTPS,确保 SSL 证书覆盖所有子域名(推荐泛域名证书
*.example.com) - 在
config/session.php中设置:'domain' => '.example.com'(开头带点) - 对应地,
config/app.php中的url应为https://example.com,而非带子域名的地址 - CSRF token 在跨子域名提交表单时也会失效,需确认
VerifyCsrfToken中间件未误判请求来源
调试子域名路由不生效的三个检查点
当路由定义写了却完全不匹配,优先排查以下三项:
- 用
php artisan route:list看输出中Domain列是否显示你配置的域名(如admin.example.com或{sub}.example.com);为空说明路由未注册成功 - 在浏览器开发者工具 Network 面板中,检查请求的
Host请求头是否确实是目标子域名(比如是localhost:8000就不可能命中admin.example.com) - 临时在路由闭包里加
dd(request()->getHost()),确认 Laravel 收到的 Host 值是否符合预期(有些代理或 Docker 环境会改写 Host)
子域名路由的复杂性不在 Laravel 代码本身,而在于网络层、DNS、SSL 和浏览器行为的协同;只要 Host 头能准确抵达 Laravel 并被正确解析,剩下的就是标准路由逻辑。











