使用 Laravel "distinct" 验证规则但忽略一些基于数组 属性 的数组条目

Use Laravel "distinct" validation rule but ignore some array entries based on an array property

我想在 Laravel 中使用表单请求验证输入数据数组。 该数组如下所示:

[
  'issues' =>
  [
     'type' => 'prio_1',
     'note' => 'This is some text'
  ],
  [
     'type' => 'prio_2',
     'note' => 'This is some other text'
  ]
  [
     'type' => 'prio_1',
     'note' => 'This is yet some other text',
     'deleted' => true
  ]
]

我想验证这个数组中的 type 字段是 distinct,考虑到第三个数组条目是 deleted 因此需要为此忽略规则。 使用

["issues.*.type" => 'required|distinct']

当然不起作用,因为如果数组 属性 具有特定值,则不能将此规则参数化以忽略该规则。 过滤输入以忽略已删除的条目也不是一个选项,因为替换响应中 * 的索引需要与请求中的原始索引匹配。

有没有办法扩展 distinct 规则(使用自定义验证器)以允许进行这种验证?或者任何其他允许这样做的方式?

您可以使用 closure and a collection 检查是否有重复项(不包括 "deleted" 项):

public function rules()
{
    return [
        "issues.*.type" => [
            'required', function ($attr, $value, $fail) {
                $count = collect($this->input('issues'))
                    ->reject(function ($item) {
                        return isset($item['deleted']) && $item['deleted'];
                    })
                    ->filter(function ($item) use ($value) {
                        return $item['type'] === $value;
                    })
                    ->count();

                if ($count > 1) {
                    $fail(__('validation.distinct'));
                }
            },
        ],
    ];
}

为了提高效率,您也可以只计算之前的值,然后检查计数是否大于 1:

public function rules()
{
    $duplicateTypes = collect($this->input('issues'))
        ->reject(function ($item) {
            return isset($item['deleted']) && $item['deleted'];
        })
        ->groupBy('type')
        ->map->count();

    return [
        "issues.*.type" => [
            'required', function ($attr, $value, $fail) use($duplicateTypes) {
                if ($duplicateTypes[$value] > 1) {
                    $fail(__('validation.distinct'));
                }
            },
        ],
    ];
}