Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 4 Validation - Nested Indexed Arrays?

Tags:

php

laravel

I have an array of various things...

$foo = [];
$foo['stuff']['item'][0]['title' => 'flying_lotus'];
$foo['stuff']['item'][1]['title' => 'various_cheeses'];
$foo['stuff']['item'][2]['title' => 'the_career_of_vanilla_ice'];
$foo['stuff']['item'][3]['title' => 'welsh_cats'];

How would I validate the 'title' key, using the Validator method in Laravel 4?

Here's what I have so far...

$validator = Validator::make($foo, ['stuff.item.???.title' => 'required']);

I'm totally flummoxed by the indexed array. Any help would be great .

like image 885
Captain flapjack Avatar asked Jul 31 '13 15:07

Captain flapjack


2 Answers

The following answer is for Laravel <= 5.1. Laravel 5.2 introduced built-in array validation.


At this time, the Validator class isn't meant to iterate over array data. While it can traverse through a nested array to find a specific value, it expects that value to be a single (typically string) value.

The way I see it, you have a few options:

1: Create rules with the array key in the field name.

Basically essentially what you're doing already, except you'd need to figure out exactly how many values your ['stuff']['item'] array has. I did something like this with good results:

$data = [
    'stuff' => [
        'item'  => [
            ['title' => 'flying_lotus'],
            ['title' => 'various_cheeses'],
            ['title' => ''],
            ['title' => 'welsh_cats'],
        ]
    ]
];

$rules = [];

for ($i = 0, $c = count($data['stuff']['item']); $i < $c; $i++)
{
    $rules["stuff.item.{$i}.title"] = 'required';
}

$v = Validator::make($data, $rules);

var_dump($v->passes());

2: Create a custom validation method.

This will allow you to create your own rule, where you can expect an array value and iterate it over as necessary.

This method has its caveats, in that A) you won't have specific value error messages, since it'll error for the entire array (such as if you pass stuff.item as the value to check), and B) you'll need to check all of your array's possible values in your custom function (I'm assuming you'll have more than just title to validate).

You can create the validation method by using the Validator::extend() or by fully extending the class somewhere else.

3: Extend the Validator class and replace/parent the rules in question to accept arrays.

Create your own extended Validator class, and either implement custom rules, or rename existing ones, enabling those rules to accept an array value if one happens along. This has some similar caveats to the #2 custom rule option, but may be the "best practice" if you intend on validating iterated arrays often.

like image 67
Aken Roberts Avatar answered Nov 17 '22 09:11

Aken Roberts


As @Cryode said, Laravel doesn't currently offer this functionality out of the box. I created a class extending the default Laravel Validator to add an iterate($attribute, $rules, $messages) method.

It can also iterate recursively through arrays so that (for example) if you have any number of "books", each of which may have any number of "citations", this will still work, which @Cryode's example does not do, so this is a little more robust.

https://github.com/penoonan/laravel-iterable-validator

like image 30
patricksayshi Avatar answered Nov 17 '22 09:11

patricksayshi