9

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 .

1
  • Im dying to see the answer to this :) I've been doing it extremely messy....by doing a foreach, then storing the result in another array, then checking that array for errors, and displaying Commented Jul 31, 2013 at 15:43

3 Answers 3

19

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for a very concise answer. I had a feeling a solution wouldn't be available 'out of the box', but your first method will work just fine. Cheers!
@Cryode, if I have nested parameter can I do it in same way as case1 , I don't have to create new rule , I just need a way to validate the form items.
2

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

2 Comments

Has this been tested using Laravel 5?
Nope. I actually submitted a pull request to have it merged into 4, though. Tests all passed, but is currently in limbo.
0

In addition to @Cryode answer, and for my laravel 5 issue.

my form has an database id index. so my form fields have the index

$foo['stuff']['item'][8]['title' => 'flying_lotus'];
$foo['stuff']['item'][12]['title' => 'various_cheeses'];
$foo['stuff']['item'][23]['title' => 'the_career_of_vanilla_ice'];

i used foreach to reach my goal

foreach($request->input()['stuff']['items'] as $key => $value){
    $rules["stuff.items.{$key}.title"] = 'required';
}

and the custom error messages

foreach($request->input()['stuff']['items'] as $key => $value){
    $messages["stuff.items.{$key}.title.required"] = 'Each Title is required...';
}

and validate

Validator::make($request->input(), $rules, $messages);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.