返回

Laravel 11 & Inertia:302 错误及表单提交问题排查指南

vue.js

Laravel 11 & Inertia:请求错误 302 排查指南

使用 Inertia 和 Laravel 开发应用时,有时提交表单会遇到 302 错误,尤其在表单数据无效的情况下。这篇文章将分析出现这种情况的常见原因,并提供相应的解决方案。

问题

在 Inertia 和 Laravel 应用中,当提交包含有效数据的表单时,请求正常完成。但提交空表单或包含无效数据时,请求返回 302 错误,并未显示预期的验证错误信息。这个问题通常与表单验证和 Inertia 的交互方式有关。

解决方案

1. 检查 API 路由

302 错误通常表示重定向。请确保 API 路由使用 Route::apiResource 或者其他 API 路由定义方式,而不要 将其定义在 web 路由中间件组内。web 路由中间件组可能会应用 CSRF 保护等机制,导致 Inertia 的 POST 请求在验证失败时被重定向。

示例:

// 正确:在 api.php 中定义
Route::apiResource('currencies', CurrencyController::class);

// 错误:在 web.php 中定义并应用了 web 中间件
Route::group(['middleware' => ['web']], function () {
    Route::apiResource('currencies', CurrencyController::class); 
});

2. 验证请求类型

Inertia 的 post 方法默认发送 JSON 格式的数据。请确认控制器方法 store 的参数类型为 RequestStoreCurrencyRequest。同时,需要使用 $request->validated() 获取验证后的数据,而不是直接使用 $request->all()

示例:

// CurrencyController.php
use Illuminate\Http\Request; // 或 use App\Http\Requests\StoreCurrencyRequest;

public function store(Request $request) // 或 public function store(StoreCurrencyRequest $request)
{
    $validatedData = $request->validated(); // 获取验证后的数据
    $currency = Currency::create($validatedData);
    return response()->json($currency, 201);
}

3. 处理验证错误

当验证失败时,Laravel 默认会返回 422 状态码以及错误信息。Inertia 可以拦截这个错误并将其传递给前端组件。需要确保前端组件正确处理 onError 回调函数中的错误。

示例:

// Vue Component
submit() {
    Inertia.post('/api/currencies', this.form, {
        onError: (errors) => {
             //确保 errors 是一个对象,其键值对对应字段名和错误信息。
            this.form.errors = errors; 
            //如果后端返回的不是 {字段: [错误信息]} 的格式,则需要进行格式转换,避免页面无法正确展示
        },
       
    });
}

4. 返回 JSON 响应

确保控制器在验证失败时也返回 JSON 响应。可以通过手动构造 JSON 响应或使用 Inertia 的 redirectBackWithError 方法。

示例 (使用 redirectBackWithError):

// CurrencyController.php

use Inertia\Inertia;
//...

public function store(StoreCurrencyRequest $request)
{

   try {
      $currency = Currency::create($request->validated());
       return response()->json($currency, 201);

    } catch (\Exception $e) { // 处理数据库错误等其他潜在问题

        return Inertia::render('Currencies/Create')->withErrors(['message' => '创建失败']); 
      //  或 return back()->withErrors(['message' => '创建失败']); // 注意!如果路由是API路由,不应该直接 return back()

    }
    
}


安全建议

  • 始终验证用户输入。使用 Laravel 的表单请求验证功能是确保应用安全的最佳实践。
  • 限制 API 速率,防止恶意请求。
  • 对敏感数据进行加密,例如密码和 API 密钥。

通过以上步骤,应该能够解决 Inertia 和 Laravel 应用中出现的 302 错误。 记住仔细检查路由配置,验证请求类型,并正确处理验证错误和响应。 确保 API 端点返回一致的 JSON 响应,即使在验证失败的情况下也是如此。 这将有助于提高应用的稳定性和用户体验。