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

Laravel表单验证:如何按条件实现product_id的distinct验证

解决同订单下产品ID不重复的验证问题

你当前用的distinct:strict是全局校验所有product_id的唯一性,不管对应的order_id是否相同,所以会出现不同订单下产品ID重复也报错的情况。要实现同一订单ID下产品ID唯一的需求,需要自定义验证逻辑,下面提供两种可行方案:

方案一:使用闭包添加后置验证

直接在验证器后追加自定义检查逻辑,适合一次性场景:

use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'inputs.*.order_id' => 'required',
    'inputs.*.product_id' => 'required',
], [
    'inputs.*.order_id.required' => '订单ID不能为空',
    'inputs.*.product_id.required' => '产品ID不能为空',
]);

// 追加同订单产品ID唯一性检查
$validator->after(function ($validator) use ($request) {
    // 按order_id分组
    $orderGroups = collect($request->input('inputs'))->groupBy('order_id');

    foreach ($orderGroups as $orderId => $items) {
        $productIds = $items->pluck('product_id')->toArray();
        // 检查组内产品ID是否有重复
        if (count($productIds) !== count(array_unique($productIds))) {
            // 全局提示重复问题
            $validator->errors()->add('inputs', "订单ID {$orderId} 下存在重复的产品ID");
            
            // 若需精准定位到重复的数组项,替换上面的错误提示为以下代码:
            // $seenProducts = [];
            // foreach ($items as $index => $item) {
            //     $productId = $item['product_id'];
            //     if (in_array($productId, $seenProducts)) {
            //         $validator->errors()->add("inputs.{$index}.product_id", "订单ID {$orderId} 下的产品ID {$productId} 重复");
            //     }
            //     $seenProducts[] = $productId;
            // }
        }
    }
});

if ($validator->fails()) {
    return redirect()->back()->withErrors($validator)->withInput();
}

方案二:自定义验证规则类(适合复用)

如果多个地方需要这个验证逻辑,可以创建自定义规则类:

1. 创建规则类

// app/Rules/UniqueProductPerOrder.php
namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Collection;

class UniqueProductPerOrder implements Rule
{
    protected $inputItems;

    public function __construct($inputItems)
    {
        $this->inputItems = $inputItems;
    }

    public function passes($attribute, $value)
    {
        // 从属性名中提取当前项的索引(比如"inputs.0.product_id"提取出0)
        $index = explode('.', $attribute)[1];
        $currentOrderId = $this->inputItems[$index]['order_id'];

        // 统计同订单ID下当前产品ID出现的次数
        $duplicateCount = collect($this->inputItems)
            ->where('order_id', $currentOrderId)
            ->where('product_id', $value)
            ->count();

        // 只允许出现一次
        return $duplicateCount === 1;
    }

    public function message()
    {
        return '同订单下不能存在重复的产品ID';
    }
}

2. 使用规则类

use Illuminate\Support\Facades\Validator;
use App\Rules\UniqueProductPerOrder;

$validator = Validator::make($request->all(), [
    'inputs.*.order_id' => 'required',
    'inputs.*.product_id' => [
        'required',
        new UniqueProductPerOrder($request->input('inputs'))
    ],
]);

if ($validator->fails()) {
    return redirect()->back()->withErrors($validator)->withInput();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 08:35:10