Laravel 9结合Inertia时子域名路由跳转异常问题
这个问题和CORS配置无关,是三处配置逻辑错误叠加导致的:
- 路由定义中直接调用
env()读取域名,加上APP_URL带协议前缀,导致路由规则匹配、地址生成异常 - 子域名路由传参用索引数组,参数错位导致生成的跳转地址丢失子域名段
- Inertia默认将同根域跳转识别为应用内XHR请求,未正确识别跨子域场景,不会更新地址栏的域名部分,仅替换路径段
1. 修正基础域名配置
首先修改.env中的APP_URL值,去掉协议前缀,只保留根域名:
APP_URL=example.test
调整路由定义的域名规则,注意:禁止在路由文件中直接调用env(),执行php artisan route:cache后路由文件内的env()调用会返回空值,直接导致子域名规则失效,必须通过config()读取配置:
Route::domain('{user:username}.' . config('app.url'))->group(function () { Route::get('{product:slug}', [ProductController::class, 'show'])->name('products.show'); });
2. 修正路由跳转传参
Laravel域路由的参数优先级高于路径参数,生成路由地址时必须用关联数组显式传入对应参数,禁止用索引数组顺序传参,避免参数错位:
public function store(StoreProductRequest $request) { // 原有业务处理逻辑 return redirect()->route('products.show', [ 'user' => $user, // 对应子域名段的{user:username}绑定参数 'product' => $product // 对应路径段的{product:slug}绑定参数 ]); }
改完后执行以下命令清除缓存,先验证路由生成是否正确:
php artisan route:clear php artisan config:clear
可以在tinker中执行以下命令验证路由生成结果,输出地址为http://[用户名].example.test/[商品slug]格式才是正常:
php artisan tinker >>> route('products.show', ['user' => User::first(), 'product' => Product::first()])
3. 调整Inertia跨子域跳转逻辑
Inertia默认仅在完全同源的地址下做无刷新跳转,跨子域属于不同源,需要在前端Vue侧的Inertia配置中添加URL解析规则,让其正确识别子域名地址,触发地址栏更新:
打开resources/js/app.js,在createInertiaApp配置项中添加resolveUrl方法:
import { createInertiaApp } from '@inertiajs/vue3' createInertiaApp({ // 保留你原有的id、title、resolve等配置 resolveUrl: (url) => new URL(url, window.location.origin), })
如果不想调整全局配置,也可以直接在后端控制器中生成绝对子域名地址,触发整页跳转:
public function store(StoreProductRequest $request) { // 原有业务处理逻辑 $productUrl = "https://{$user->username}." . config('app.url') . "/{$product->slug}"; return redirect()->away($productUrl); }
4. 修正CORS配置的安全风险
你当前的CORS配置全量放开所有源,生产环境存在跨域请求伪造风险,调整为仅允许主域和子域访问即可:
'paths' => ['api/*', 'sanctum/csrf-cookie', '*'], 'allowed_methods' => ['*'], 'allowed_origins' => ['example.test', '*.example.test'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => ['x-inertia'], 'max_age' => 0, 'supports_credentials' => true, // 项目使用Sanctum做会话认证时必须开启该选项
修改完成后重新执行php artisan config:cache、php artisan route:cache生效配置,清空浏览器缓存后测试即可:创建商品跳转后地址栏会显示正确的子域名地址,刷新页面也不会触发404。
内容的提问来源于stack exchange,提问作者Mostafa Said

