Laravel 11 中 route() 默认不生成子域名 URL,需显式指定:用 route('name', $params, ['domain' => 'sub.example.com'])、url('/path', [], 'https://sub.example.com') 或 app('url')->forceRootUrl()。

在 Laravel 11 中,Route::domain() 定义的子域名路由本身**不自动影响 URL 生成逻辑**——也就是说,route() 函数默认只关心路由名和参数,**不会主动拼出子域名**。要生成带子域名的 URL,必须显式告诉 Laravel 当前请求或生成上下文应使用哪个子域名。
关键前提:确保 APP_URL 和 SESSION_DOMAIN 配置正确
生成子域名 URL 不是纯 PHP 逻辑,它依赖框架对“当前域”的认知:
-
APP_URL 必须设为带主域名的格式,例如
https://example.com(不含子域名),否则url()和route()会错误地以它为基准拼接 -
SESSION_DOMAIN 应设为
.example.com(开头带点),保证 Cookie 能被所有子域名共享,这对登录态一致很重要 - DNS 或
/etc/hosts需已支持泛解析(如*.example.com指向本地),否则生成的 URL 即使格式正确也无法访问
方法一:用 route() + domain 参数(推荐)
Laravel 9+(含 11)支持在 route() 调用时传入 domain 键,强制指定子域名:
{{ route('shop.cart', ['id' => 123], ['domain' => 'shop.example.com']) }}
// 生成:https://shop.example.com/cart?id=123
注意:
- 第三个参数是数组,必须包含
'domain'键,值为完整子域名(协议由当前请求或APP_URL决定) - 该方式适用于命名路由,且要求该路由确实在
Route::domain('shop.example.com')组内定义过 - 如果想动态取租户名(如
tenant1.example.com),可传变量:['domain' => $tenant . '.example.com']
方法二:用 url() 手动拼接(适合非命名路由或临时场景)
当没有命名路由,或只是跳转到静态路径时,url() 更直接:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
{{ url('/cart', [], 'https://shop.example.com') }}
// 生成:https://shop.example.com/cart
说明:
- 第三个参数是完整协议 + 域名,Laravel 会将其作为根地址,再拼上第一个参数的路径
- 不校验路由是否存在,也不注入参数,适合资源链接、第三方回调地址等
- 若协议不确定,可用
request()->getSchemeAndHttpHost()动态获取当前请求的 host,再替换子域名部分
方法三:全局配置默认 domain(谨慎使用)
可在中间件或服务提供者中,通过 UrlGenerator 强制设置默认域:
// 在 AppServiceProvider@boot 或专用中间件中
app('url')->forceRootUrl('https://admin.example.com');
效果:
- 此后所有
route()和url()生成的 URL 都基于该域名 - 适合整个请求生命周期都绑定单一子域名的场景(如后台管理域)
- 但多租户环境下不推荐全局强设,容易污染其他请求;应优先用方法一按需指定
不复杂但容易忽略:子域名 URL 的生成不是靠路由定义自动推导的,而是靠你明确告诉框架“这次要发往哪个域”。只要 route() 传 domain、url() 给全地址、或 UrlGenerator 强制根路径,就能准确输出。










