Petyor
Petyor

Reputation: 404

How to access nested item in Rule::requiredIf() validation

I'm trying to validate an array inside a custom Request. The rule evaluates to required if two conditions are met:

  1. attribute3 is true
  2. another column from the same array is true

Here's what I'm doing:

public function rules()
{
    return [
        'attribute1' => 'required',
        'attribute2' => 'required',
        'attribute3' => 'required',
        ...
        'attribute10.*.column3' => Rule::requiredIf(fn() => $this->attribute3), // <- array
        'attribute10.*.column4' => Rule::requiredIf(fn() => $this->attribute3), // <- array
        'attribute10.*.column5' => Rule::requiredIf(fn() => $this->attribute3), // <- array
    ];
}

What I really need is this:

'attribute10.*.column4' => Rule::requiredIf(fn($item <- magically hint this currently looped item) => $this->attribute3 && $item->column2 <- so I can use it like this), // <- array

Upvotes: 2

Views: 1436

Answers (2)

Amin.Qarabaqi
Amin.Qarabaqi

Reputation: 723

You can try foreach validation rule.
here is an example from documents:

$validator = Validator::make($request->all(), [
    'companies.*.id' => Rule::forEach(function ($value, $attribute) {
        return [
            Rule::exists(Company::class, 'id'),
            new HasPermission('manage-company', $value),
        ];
    }),
]);

Upvotes: 0

porloscerros Ψ
porloscerros Ψ

Reputation: 5098

Assuming the incoming request has a structure like the following:

[
    'attribute1' => 1,
    'attribute2' => 0,
    'attribute3' => 1,
    'attribute10' => [
        [
            'column1' => 1,
            'column2' => 1,
            'column3' => 0,
        ],
        [
            'column1' => 0,
            'column2' => 1,
            'column3' => 0,
        ],
    ],
]

You can set the rules array to a variable, and then loop over the attribute10 field array elements and merge each rule on the rules variable. Then you'll have access to the other elements on the nested array.
Ie:

public function rules()
{
    $rules = [
        'attribute1' => 'required',
        'attribute2' => 'required',
        'attribute3' => 'required',
    ];
    foreach($this->attribute10 as $key => $item) {
        array_merge($rules, [
            'attribute10.'.$key.'.column2' => Rule::requiredIf($this->attribute3 && $item['column1']),
            'attribute10.'.$key.'.column3' => Rule::requiredIf($this->attribute3 && $item['column2']),
            //...
        ]);
    }
    return $rules;
}

Upvotes: 2

Related Questions