Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel sometimes validation on arrays

Tags:

Suppose we have the following form data:

{age: 15, father: "John Doe"}

We want to have some complex logic behind validating the father field based on other data for the same item (for this example, we want to validate that father has at least 5 characters when age < 18).

This could be done like that:

Standard validation rules: ['age': 'required|integer']

$validator->sometimes('father', 'required|min:5', function($data) {
    return $data['age'] < 18;
});

Now, we want to have the same kind of thing with a list of items. So now, we have the following form data:

[
  {age: 25, },
  {age: 15, father: "John Doe"},
  {age: 40, },
]

Common validation rule now looks like that:

['items.*.age': 'required|integer']

My issue is now to easily express the sometimes rule for each item's father field which will depend on the item's age field.

$validator->sometimes('items.*.father', 'required|min:5', function($data) {
    // Does not work anymore: return $data['age'] < 18;
    // Any way to know which item we are dealing with here?
});

One way I could think of is to loop over the items in a validator after callback. But that does not seem very elegant :(

like image 770
Vincent Mimoun-Prat Avatar asked Nov 30 '18 09:11

Vincent Mimoun-Prat


1 Answers

Couldn't get sometimes() to work in a way you need. sometimes() doesn't "loop" over array items, it gets called a single time.

I came up with an alternative approach, which isn't perfect, but maybe you'll find it useful.

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules()
{
    Validator::extend('father_required_if_child', function ($attribute, $value, $parameters, $validator) {

        $childValidator = Validator::make($value, [
            'age' => 'required|integer'
        ]);

        $childValidator->sometimes('father', 'required|min:5', function($data) {
            return is_numeric($data['age']) && $data['age'] < 18;
        });

        if (!$childValidator->passes()) {
            return false;
        }

        return true;

        // Issue: since we are returning a single boolean for three/four validation rules, the error message might
        // be too generic.

        // We could also ditch $childValidator and use basic PHP logic instead.
    });

    return [
        'items.*' => 'father_required_if_child'
    ];
}

Curious to learn how this could be improved.

like image 75
Andrius Rimkus Avatar answered Sep 21 '22 09:09

Andrius Rimkus