Laravel动态Rak字段表单必填验证不生效问题排查
问题描述
需要为表单中动态新增的字段配置验证规则:当前仓库的name、desc字段验证已经开发完成,但无法为Rak字段配置正确的验证规则,核心要求是Rak字段为必填项,必须由用户填写,现有代码无法触发预期的验证错误提示。
现有Blade模板代码
@extends('layout.main') @Section('container') <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom"> <h1 class="h2">Create Warehouse</h1> </div> <div class="col-lg-7"> <form method="post" action="/warehouse" id="myForm" name="myForm"> @csrf <div class="row mb-2"> <label for="name" class="col-sm-2 col-form-label col-form-label-sm">Name</label> <div class="col-sm-10"> <input type="text" class="form-control form-control-sm @error('name') is-invalid @enderror" id="name" name="name" value="{{ old('name') }}"> @error('name') <div id="validationServernameFeedback" class="invalid-feedback"> {{ $message }} </div> @enderror </div> </div> <div class="row mb-2"> <label for="desc" class="col-sm-2 col-form-label col-form-label-sm">Description</label> <div class="col-sm-10"> <input type="text" class="form-control form-control-sm @error('desc') is-invalid @enderror" id="desc" name="desc" value="{{ old('desc') }}"> @error('desc') <div id="validationServercust_add1Feedback" class="invalid-feedback"> {{ $message }} </div> @enderror </div> </div> <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom"> <h1 class="h4">Rak</h1> </div> <div class="row" id="row"> <div class="col-sm-5"> <div class="input-group m-1"> <div class="input-group-prepend"> <button class="btn btn-danger btn-sm border-0" id="DeleteRow" type="button"> <i class="bi bi-trash" data-feather="x-circle"></i> </button> </div> <input type="text" class="typehead form-control form-control-sm @error('rak') is-invalid @enderror" placeholder="Rak Name" name="rak" id="rak_1"> @error('rak') <div id="validationServerrakFeedback" class="invalid-feedback"> {{ $message }} </div> @enderror </div> </div> <div class="col-sm-5"> <div class="input-group m-1"> <input type="text" class="form-control form-control-sm" placeholder="Rak Description" name="rak_desc[]" id="rakdesc_1" > </div> </div> </div> <div id="newinput"></div> <div class="row mb-5 mt-3 "> <div class="col-sm-10"> <button id="rowAdder" type="button" class="btn btn-dark btn-sm float-end border-0 "> <span class="bi bi-plus-square-dotted"></span> Add rak </button> </div> </div> <button type="submit" class="btn btn-primary">Create</button> </form> </div> @endsection
现有控制器代码
public function store(Request $request) { $validatedData = $request->validate([ 'name' => 'required|max:255', 'desc' => 'required|max:255', ]); foreach ($request->rak as $index => $name) { $validatedData = $request->validate([ 'rak'.$index => 'required|max:255' ]); $validatedRak['rak_name'] = $name; $validatedRak['created_by'] = auth()->user()->id; $validatedRak['updated_by'] = auth()->user()->id; $validatedRak['branch'] = auth()->user()->branch; $validatedRak['warehouse_name'] = $request->name; dd($validatedRak); warehouserak::create($validatedRak); } $validatedData['created_by'] = auth()->user()->id; $validatedData['updated_by'] = auth()->user()->id; $validatedData['branch'] = auth()->user()->branch; warehouse::create($validatedData); $request->session()->flash('Success','Warehouse Created Successfully!'); return redirect('/warehouse'); }
问题根因
- 前端默认Rak输入框的
name属性写为单值rak,不是数组格式,动态新增的Rak字段如果没有统一命名规则,后端拿到的字段结构和预期不符,循环遍历逻辑直接失效 - 后端验证逻辑写在循环内部,错误拼接
rak.$index作为验证字段名,和前端实际传参的字段名完全不匹配,验证规则根本不会命中对应字段 - 前端错误提示仅绑定了
@error('rak')单字段规则,就算后端返回数组字段的验证错误,前端也无法正常渲染提示 - 代码中残留的
dd($validatedRak)会中断程序执行,后续创建逻辑永远不会运行
修复方案
第一步:调整前端表单命名
所有Rak名称输入框统一使用数组格式的name属性:
- 将默认行的Rak输入框修改为:
<input type="text" class="typehead form-control form-control-sm @error('rak.0') is-invalid @enderror" placeholder="Rak Name" name="rak[]" id="rak_1" value="{{ old('rak.0') }}"> @error('rak.0') <div id="validationServerrakFeedback" class="invalid-feedback"> {{ $message }} </div> @enderror
- 编写动态新增行的JS逻辑时,新增的Rak名称输入框统一使用
name="rak[]",Rak描述保持name="rak_desc[]",新增行的错误提示对应匹配rak.索引值的错误规则即可。
第二步:重写后端验证与存储逻辑
Laravel原生支持数组字段验证,不需要在循环内单独写验证规则,一次性完成全字段校验即可:
public function store(Request $request) { // 一次性完成所有字段验证,包括动态数组字段 $validatedData = $request->validate([ 'name' => 'required|max:255', 'desc' => 'required|max:255', 'rak' => 'required|array|min:1', // 强制rak为数组格式,至少提交1个值 'rak.*' => 'required|max:255', // 校验rak数组下每一项都必填、长度不超过255 'rak_desc' => 'array', 'rak_desc.*' => 'nullable|max:255', // Rak描述为选填,可根据业务调整规则 ]); // 先创建仓库主数据 $warehouse = warehouse::create([ 'name' => $validatedData['name'], 'desc' => $validatedData['desc'], 'created_by' => auth()->user()->id, 'updated_by' => auth()->user()->id, 'branch' => auth()->user()->branch, ]); // 循环创建每个Rak货架数据 foreach ($validatedData['rak'] as $index => $rakName) { warehouserak::create([ 'rak_name' => $rakName, 'rak_desc' => $validatedData['rak_desc'][$index] ?? null, 'created_by' => auth()->user()->id, 'updated_by' => auth()->user()->id, 'branch' => auth()->user()->branch, 'warehouse_id' => $warehouse->id, // 建议用ID关联主从数据,不要仅存仓库名称 ]); } $request->session()->flash('Success','Warehouse Created Successfully!'); return redirect('/warehouse'); }
注意:如果需要验证失败后回显动态新增的行内容,可以在Blade中遍历
old('rak', [])循环输出所有用户已填写的行,默认保留1行空输入框即可。
内容的提问来源于stack exchange,提问作者Lodeweyk Andri
相关产品推荐
相关产品推荐

