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

Laravel8 如何使用FormRequest验证AJAX JSON请求简化控制器代码

问题:Laravel中如何让FormRequest适配AJAX JSON请求场景

问题描述

我使用Laravel的时间不长,一直在学习相关开发最佳实践,想要实现带表单验证的AJAX JSON请求。我了解到创建继承FormRequest的自定义请求类可以更好地管理参数校验逻辑,从而尽可能简化控制器代码。我目前是直接在控制器中使用Validator进行验证,不清楚如何结合JSON和AJAX场景适配FormRequest方案。

初始代码

控制器代码

public function store(Request $request)
{
    if($request->ajax()) {
        $messages = [
            'nombre.required'       => 'El campo nombre es necesario',
            'descripcion.required'  => 'El campo descripción es necesario',
        ];
        $rules = [
            'nombre' => 'required',
            'descripcion' => 'required',
            'url' => 'required|alpha_dash'
        ];
        $validator = Validator::make($request->all(), $rules, $messages);
        if ($validator->fails()) {
            return response()->json([
                'status' => 400,
                'errors' => $validator->messages()//$validator->errors()
            ]);
        } else {
            $crear = new Proyecto([
                'nombre'      => $request->nombre,
                'descripcion' => $request->descripcion,
                'url'         => $request->url
            ]);
            $crear->save();
            
            return response()->json([
                'status' => 200,
                'message' => 'Registro insertado con éxito'
            ]);

        }
    }else{
        return view("404");
    }
}

模型代码

class Proyecto extends Model
{
   use HasFactory;
   protected $table = 'proyecto';
   protected $primaryKey = 'id_proyecto';
   protected $fillable = ['nombre', 'descripcion', 'url'];
   public function getRouteKeyName()
   {
       return 'url';
   }
}

前端JS代码

$('#crear_proyecto').submit(function(e){
    e.preventDefault();

    var formu = $("#crear_proyecto").serialize();

    $.ajax({
        type: "POST",
        url: "proyecto/crearproyecto",
        data: formu,
        dataType: "json",
        beforeSend:function(){
            $(".loader").show();
        },
        success: function (data) {
            $('#crear_proyecto').find('span.text-danger').remove();
            if (data.status == 400) {
                $.each(data.errors, function (key, error_value) {
                    $('#'+key).after("<span class='text-danger'>"+error_value+"</span>");
                });
                $(".loader").fadeOut("slow");
            }else{
                $(".loader").fadeOut("slow");
                alert(data.message);
                $('#crear_proyecto').trigger("reset");
                $("#nombre").focus();
                $('#modalformu').modal('toggle');
            }
        }
    });

个人调整后的代码

调整后控制器代码

public function store(PostProyectoRequest $request)
{
    $crear = new Proyecto([
        'nombre'      => $request->nombre,
        'descripcion' => $request->descripcion,
        'url'         => $request->url
    ]);

    $crear->save();
    return response()->json([
        'status' => 200,
        'message' => 'Registro insertado con éxito'
    ]);
}

调整后自定义请求类代码

namespace App\Http\Requests;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Validator;

class PostProyectoRequest extends FormRequest
{
 /**
  * Determine if the user is authorized to make this request.
  *
  * @return bool
  */
  public function authorize()
  {
     return true;
  }

  /**
  * Get the validation rules that apply to the request.
  *
  * @return array
  */
  public function rules()
 {
     return [
         'nombre'      => 'required',
         'descripcion' => 'required',
         'url'         => 'required|alpha_dash'
     ];
 }

 public function messages()
 {
     return [
         'nombre.required'       => 'El campo nombre es necesario',
         'descripcion.required'  => 'El campo descripción es necesario'
     ];
 }
 protected function failedValidation(Validator $validator)
 {
    if($this->wantsJson())
    {
        $response = response()->json([
            'status' => 400,
            'errors' => $validator->errors()//$validator->errors()
        ]);
    }else{
        $response = redirect()
            ->route('guest.login')
            ->with('message', 'Ops! Some errors occurred')
            ->withErrors($validator);
    }

    throw (new ValidationException($validator, $response))
        ->errorBag($this->errorBag)
        ->redirectTo($this->getRedirectUrl());
}
}

回答

你调整完成后的代码完全符合Laravel开发最佳实践,已经完美适配AJAX JSON请求场景,无需额外修改即可正常运行。

实现优势

  • 校验逻辑完全从控制器抽离到自定义PostProyectoRequest请求类中,控制器仅需要处理核心的业务存储和成功响应逻辑,代码大幅轻量化,后续修改校验规则、调整提示文案仅需要修改请求类即可,维护成本显著降低
  • 重写failedValidation方法时使用Laravel原生提供的wantsJson()方法判断请求类型,会自动识别请求头参数区分AJAX请求和普通表单请求,返回的错误响应格式和你之前在控制器中手写的格式完全一致,现有前端JS代码不需要做任何调整即可兼容
  • 授权逻辑统一放在authorize方法中管理,后续如果需要加权限校验只需要修改该方法的返回值即可,不需要改动控制器代码

可选优化

你可以将非JSON请求的响应逻辑调整为和你最初代码一致的404页面,只需要把PostProyectoRequest中failedValidation方法的非JSON分支代码替换为如下内容即可:

$response = response()->view('404', [], 404);

内容的提问来源于stack exchange,提问作者Sylar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:36:02