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

Laravel如何在Request文件中校验两个数组字段的组合唯一性

Laravel 表单校验实现同索引数组组合唯一

实现思路

校验分三层执行,避免漏判:

  • 基础格式校验:保证floor_id、material_id、quantity三个字段均为数组,且数组长度完全一致,从根源避免索引错位
  • 提交内容自校验:保证本次提交的 payload 内部,没有出现同索引floor_id+material_id重复的情况
  • 数据库唯一校验:保证数据库中不存在相同的floor_id+material_id绑定关系,避免重复绑定

具体实现代码

直接在自定义的 FormRequest 文件中编写规则即可:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
use Illuminate\Support\Facades\DB;

class BindMaterialRequest extends FormRequest
{
    public function authorize()
    {
        // 根据自身权限逻辑调整,返回true代表已通过鉴权
        return true;
    }

    public function rules()
    {
        return [
            'project_id' => 'required|integer|exists:projects,id',
            'date' => 'required|date_format:m-d-Y',
            'floor_id' => 'required|array',
            'floor_id.*' => 'required|integer|exists:floors,id',
            'material_id' => 'required|array|size:'.count($this->input('floor_id', [])),
            'material_id.*' => 'required|integer|exists:materials,id',
            'quantity' => 'required|array|size:'.count($this->input('floor_id', [])),
            'quantity.*' => 'required|numeric|min:0',
        ];
    }

    public function withValidator(Validator $validator)
    {
        $validator->after(function (Validator $validator) {
            // 基础校验已报错时不再执行后续组合校验,避免冗余报错
            if ($validator->errors()->isNotEmpty()) {
                return;
            }

            $floorIds = $this->input('floor_id');
            $materialIds = $this->input('material_id');
            $bindPairs = [];
            $relationTable = 'floor_material'; // 替换为实际存储楼层-材料绑定关系的表名

            foreach ($floorIds as $index => $floorId) {
                $pairKey = $floorId . '-' . $materialIds[$index];
                // 校验本次提交内部是否存在重复组合
                if (in_array($pairKey, $bindPairs)) {
                    $validator->errors()->add(
                        'floor_id.'.$index,
                        '同一楼层下不能重复绑定相同材料'
                    );
                    continue;
                }
                $bindPairs[] = $pairKey;

                // 校验数据库中是否已存在该绑定关系
                $exists = DB::table($relationTable)
                    ->where('floor_id', $floorId)
                    ->where('material_id', $materialIds[$index])
                    // 编辑场景下新增该行排除当前记录:->where('id', '!=', $this->route('绑定记录ID'))
                    ->exists();

                if ($exists) {
                    $validator->errors()->add(
                        'floor_id.'.$index,
                        '楼层ID为'.$floorId.'下已绑定材料ID为'.$materialIds[$index].'的记录,请勿重复提交'
                    );
                }
            }
        });
    }
}

注意事项

  • 代码中floor_material表名需要替换为实际存储楼层和材料绑定关系的数据表名
  • 编辑场景下在数据库查重逻辑中增加排除当前记录ID的条件即可,避免将自身记录判定为重复
  • 错误提示文案、错误挂载的字段位置可根据业务需求调整,方便前端定位对应表单项

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:12:23