How To: Validate an array of form fields with Laravel

Note: This tutorial is only relevant for Laravel 5.1 and lower. Laravel 5.2 has improved how this works.

If you’ve used Laravel’s form validation for any length of time, then you know it’s a powerful system. It makes the tedious task of validation very simple while still keeping the door open for complex rules.

In this tutorial, I want to show you a simple and easy way of validating forms that contain dynamic fields. A common use case for these types of forms is when you would like to allow a user to add more fields to a form.

Here is a visual representation of the form:

In a real world scenario clicking the “Add New” button would load in a new input field with the field name being an array. All of that would happen with JavaScript and is beyond the scope of this tutorial however if you’d like to see a quick way of doing it have a look at this thread.

Here is a quick PHP mockup of the view for demonstrating the form fields:

To handle the actual validation Laravel gives us a few options. The Validation::make facade, Controller validation, and the new Form Requests. For this tutorial, I’ll step through using the new Form Request feature. This same code can be adapted to both the other options.

Creating a new form request

To create the Form Request class, we can utilize Artisan to have the system automatically generate the file. Open terminal and cd into your directory and then run:

$ php artisan make:request OrderRequest
Request created successfully.

Next open this new file which is at the following location app/Http/Requests/OrderRequest.php. You should see this content:

Adjust the Authorize

The first step is to modify the authorize() method. This method allows you to restrict access by returning true or false. For example, you could check a user group, or some other form of access and deny it if they failed to be a part of the group. Change this to return true to bypass any checks:

public function authorize()
{
return true;
}

Adding Custom Validation Rules

In that same file, you’ll see the next method is rules and this where you need to define you custom validation rules. You can find a complete list of rules via the official documentation. In our case, we want to keep it simple and force the name field to be required, and then each book title the user would like to purchase must be less than 10 characters in length.

You can use any logic you’d like in the rules() method as long as you return an array.

In order to handle the dynamic fields, you will need to loop through all the posted “items” and add a rule for each. Here is an updated method demonstrating this:

What we are doing here is first setting the required name field and then looping through all of the $_POST items to dynamically set the validation for each one. The important area to take notice of is the array key. Laravel allows you to use the dotted syntax for each item. For example $rules[‘items.1’] would map to:

<input name="items[1]"

This can be confusing if you are new to the framework and is easy to miss.

If you now try to submit the form in the browser, you may notice a problem. The failed validation gives us this error message:

Your user at this point is going to be scratching their head thinking what is “items.0”? To fix this Laravel also allows a messages method where you can set any custom messages that will be returned to the user.

Form Request Validation Messages

To fix this, you will need to add a custom message for each item. Here is the completed method:

Just like rules() we are looping through the items and specifically targeting the max rule to display a custom message and more importantly remove the “items.0”. Now our error message will be displayed like this:

Conclusion

As you can see, Laravel’s form validation is powerful, and the new form requests are a nice addition to Laravel 5. If you’d like to see all the code associated with this tutorial check out the complementary GitHub repo. If you have any questions or comments feel free to share below.

Ideally I’d have JavaScript validation first which should catch 95% of any errors. Going off the top of my head I’d think you would want to check the Input for “items” then loop Input::get('items') in your view and have the fields display again with the value set.

Sort of hard to explain in a comment, but I think that would be the basics of it. If you’d like me to clarify more or give an example let me know.

Hey! Related to dynamically created fields, I’ve run into a problem. I’ve tried sending the inputs to view – at validation failed, check if the array it is set, is yes, run a foreach to recreate the inputs and populate them – but the inputs are not displayed and so the values are missing). It would be amazing if you could show me a simple example. By the way, I’m on laravel 4. Thank you

I’m using your approach to validate input arrays, but Laravel doesn’t seem to remove the index while testing for the “unique:tablename” rule, so for example if I have $rules[‘username.’.$idx] = ‘required|max:60|unique:users’; Laravel tries to find a column called “esername.8” (for example) in the users table. Or maybe I’mmissing something? 😀

For example, if the user did not submit any items, the validation rules won’t even kick up. I need to validate so user need to submit at least one item.

I’m migrating my site from Codeigniter to Laravel, in Codeigniter it’s much more easier. You just put ‘[]’ behind the field name, so just use ‘items[]’ as the field name and the validation will work on array.
The array file validation also has bug too, it won’t return error message.

Hi Eric, Nice Tutorial
I am using Laravel 5.2 but haven’t found a way to fill up a select in a form array with the proper old() values even when I am passing the correct old(). form helper is setting the selected to all the inputs in the array which were selected . Has anybody found a way for this this.
Thanks.

The validation will simply fail if you dont send the dynamic field in the request as the rule is being generated on run time from the requests parameters and if you dont send that parameter the rule will not be generated where as your rules array says the field is “required” so that check will certainly fail.

Using OctoberCMS with laravel/Core 5.1, I have to deal with an issue with validation array input. I have already lost 4 days before finding this page. I use jquery.repeater so my input fields are formatted like that

group-name[0][field_name]

i have to display error message for each field in an with attribute data-validate-for=”group-name[0][field_name]”

can i simply use trick you describe here to make matching error message with corresponding field

i tried

group-name.0.[field_name]

group-name.0.field_name

but still doesn’t work
can i use this syntax or have to change the structure of my field name by hacking jquery.repeater like