You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:24:51