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
相关产品推荐
相关产品推荐

