Noman Ur Rehman
Noman Ur Rehman

Reputation: 6947

Laravel: Using validator's sometimes method when input is an array

I have a form that posts a structure field as an array. The structure array contains definitions of database table columns.

$validator = Validator::make($request->all(), [
    'structure' => 'required|array|min:1',
    'structure.*.name' => 'required|regex:/^[a-z]+[a-z0-9_]+$/',
    'structure.*.type' => 'required|in:integer,decimal,string,text,date,datetime',
    'structure.*.length' => 'nullable|numeric|required_if:structure.*.type,decimal',
    'structure.*.default' => '',
    'structure.*.index' => 'required_if:is_auto_increment,false|boolean',
    'structure.*.is_nullable' => 'required_if:is_auto_increment,false|boolean',
    'structure.*.is_primary' => 'required_if:is_auto_increment,false|boolean',
    'structure.*.is_auto_increment' => 'required_if:structure.type,integer|boolean',
    'structure.*.is_unique' => 'required_if:is_auto_increment,false|boolean',
    'structure.*.decimal' => 'nullable|numeric|required_if:structure.*.type,decimal|lt:structure.*.length',
]);

Without going into explanation of all the rules, one thing should be made sure that the length field is always null when the type is not string or decimal as you cannot assign a length to columns other than these types. So, I am trying to use the sometimes method on the $validator instance.

$validator->sometimes('structure.*.length', 'in:null', function ($input) {
    // how to access the structure type here?
});

My question is inside the closure, how do I make sure that the length is null only for the array element that has the type set to other than string or decimal.

I have tried the dd function and it seems the whole input array is passed to the closure.

$validator->sometimes('structure.*.length', 'in:null', function ($input) {
    dd($input);
});

Here is the output of the dd method.

Output of the <code>dd</code> method

I can use a foreach construct but wouldn't that be inefficient? Checking all the elements for a single element?

How do I check the type only for the array element under consideration?

Is there a Laravel way to do this?

Upvotes: 7

Views: 1293

Answers (2)

Hayato
Hayato

Reputation: 56

How about thinking opposite? if the Type is String or Decimal, the Length field will become Required.

$validator->sometimes('structure.*.length', 'required', function ($input) {
    return $input->type == 'string' or $input->type == 'decimal';
});

Upvotes: 1

Mozammil
Mozammil

Reputation: 8750

This is a great question. I took a look at the API for sometimes(). It seems, what you want to do, is currently not possible with it.

A possible alternative could be to use an After Validation Hook. For example:

$validator->after(function ($validator) {
    $attributes = $validator->getData()['structure'];

    foreach($attributes as $key => $value) {
        if(! in_array($value['type'], ['string', 'decimal']) && ! is_null($value['length'])) {
            $validator->errors()->add("structure.{$key}.length", 'Should be null');
        }
    }
});

Upvotes: 0

Related Questions