Laravel 11+Vue3+Axios提交POST请求遇422验证错误问题
Vue3 Axios请求Laravel11 API验证失败无法自定义返回消息的问题
问题说明
使用Vue3的Axios向Laravel11 API发送POST登录请求时,验证逻辑正常触发,但当验证失败($data->fails())时,Laravel直接返回422状态码的JSON错误响应,导致无法执行后续自定义返回消息的代码。已安装laravel/breeze --api包,后端运行地址http://localhost:8000,前端运行地址http://localhost:8080。
环境配置
.env 文件
APP_NAME='Laravel' APP_ENV=local APP_KEY=base64:RXw+M7zZjmXJOaBwk8+MGeEHPs23HKza0CcFMTRO+30= APP_DEBUG=true APP_TIMEZONE=Asia/Tehran APP_URL=http://localhost:8000 FRONTEND_URL=http://localhost:8080 SANCTUM_STATEFUL_DOMAINS=localhost:8080 SESSION_DOMAIN=localhost
bootstrap/app.php 配置
<?php use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { $middleware->api(prepend: [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, ]); $middleware->alias([ 'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class, ]); $middleware->validateCsrfTokens(except: [ '*', ]); }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
前端代码
axios.js
import axios from "axios"; axios.defaults.withCredentials = true; axios.defaults.baseURL = "http://localhost:8000/";
main.js
import { createApp } from 'vue' import App from './App.vue' import router from './router' import 'bootstrap/dist/css/bootstrap.rtl.min.css' import 'bootstrap' import '../axios' const app = createApp(App) app.use(router) app.mount('#app')
Login.vue 组件
<template> <div class="container"> <div class="col-lg-6 mx-auto"> <h1 class="lh-lg">登录</h1> <form @submit.prevent="submitLogin"> <div class="mb-3"> <label for="email" class="form-label">邮箱</label> <input type="text" class="form-control" id="email" name="email" v-model="form.email"> </div> <div class="mb-3"> <label for="password" class="form-label">密码</label> <input type="password" class="form-control" id="password" name="password" v-model="form.password"> </div> <div class="mb-3"> <button type="submit" class="btn btn-primary btn-lg">登录</button> </div> </form> </div> </div> </template> <script setup> import { ref } from 'vue'; import axios from 'axios'; import { useRouter } from 'vue-router'; const router = useRouter(); const form = ref({ email: '', password: '' }); const getToken = async () => { await axios.get('/sanctum/csrf-cookie'); } const submitLogin = async () => { console.log('表单值:', form.value); await getToken(); try { await axios.post('/login', { email: form.value.email, password: form.value.password, }); router.push('/'); } catch (error) { console.error('请求错误:', error.response.data); } } </script>
解决方法
后端:自定义验证失败响应
Laravel默认会在验证失败时抛出ValidationException并自动返回422响应,要自定义返回内容,有两种方式:
方式1:控制器手动处理验证
修改登录控制器(app/Http/Controllers/Auth/AuthenticatedSessionController.php)的store方法,手动执行验证并返回自定义响应:
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\RateLimiter; public function store(Request $request) { $validator = Validator::make($request->all(), [ 'email' => 'required|string|email', 'password' => 'required|string', ]); if ($validator->fails()) { return response()->json([ 'message' => '请检查输入的邮箱和密码格式', 'errors' => $validator->errors() ], 422); } if (!Auth::attempt($request->only('email', 'password'), $request->boolean('remember'))) { RateLimiter::hit($request->throttleKey()); return response()->json(['message' => '邮箱或密码错误'], 401); } RateLimiter::clear($request->throttleKey()); $request->session()->regenerate(); return response()->json([ 'message' => '登录成功', 'user' => Auth::user() ]); }
方式2:全局异常处理
在bootstrap/app.php的异常配置中,自定义ValidationException的响应格式:
->withExceptions(function (Exceptions $exceptions) { $exceptions->render(function (\Illuminate\Validation\ValidationException $e, $request) { if ($request->wantsJson()) { return response()->json([ 'message' => '输入验证失败', 'errors' => $e->errors() ], $e->status); } }); })->create();
前端:捕获并处理422错误
在Vue组件的请求逻辑中,通过try/catch捕获Axios的错误响应,获取后端返回的自定义消息:
const submitLogin = async () => { console.log('表单值:', form.value); await getToken(); try { const res = await axios.post('/login', form.value); alert(res.data.message); router.push('/'); } catch (err) { if (err.response.status === 422) { alert(err.response.data.message); // 可遍历errors展示字段级错误 console.log(err.response.data.errors); } else if (err.response.status === 401) { alert(err.response.data.message); } } }
内容的提问来源于stack exchange,提问作者Developer Laravel
相关产品推荐
相关产品推荐

