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:
<input type="text" class="form-control" name="name" value="name">
@for ($i=0; $i < 2; $i++)
<input type="text" name="items[{{ $i }}]" value="{{ $i }}">
@endforeach
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:
<?php namespace AppHttpRequests;
use AppHttpRequestsRequest;
class OrderRequest extends Request {
public function authorize()
{
return false;
}
public function rules()
{
return [
//
];
}
}
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:
public function rules()
{
$rules = [
'name' => 'required|max:255',
];
foreach($this->request->get('items') as $key => $val)
{
$rules['items.'.$key] = 'required|max:10';
}
return $rules;
}
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:
public function messages()
{
$messages = [];
foreach($this->request->get('items') as $key => $val)
{
$messages['items.'.$key.'.max'] = 'The field labeled "Book Title '.$key.'" must be less than :max characters.';
}
return $messages;
}
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.
How would you deal with array validation with multiple fields grouped together? For example you now want the user to enter their favourite character in each of their favourite books?
LikeLike
It would pretty much be the same. Loop through the request and add each character into the $rules array. The important part would be using the dotted syntax in the array key:
$rules[‘items.’ . $key . ‘.’ . $character]
LikeLike
That’s a great post, thanks! I have a question though:
When validation fails how do you manage to populate the dynamically generated fields?
LikeLike
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.
LikeLike
Yeah that’s how I was doing it before, I didn’t realized that this changed with Laravel 5 though: you need to use
Form::old('items')
for this to work now.LikeLike
Another way is to append ->with(‘input’) to your redirect back.
LikeLike
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
LikeLike
Oops, I mean ->withInput()
LikeLike
If nothing gets submitted, i.e. if
$this->request->get('items')
is null, this is going to fail for fields that are required, right?LikeLike
Really nice thing! Thanks Eric!
LikeLike
Thank you for this tutorial!
However I cant make file input validation. My “FormRequest” class doesn’t catch any file input. Maybe you know where is the problem?
LikeLike
When you say “file input” are you attempting to upload files and validating those? Maybe you can create a gist with your FormRequest code so I’d get a better idea of what you are doing.
LikeLike
Just resolved my problem. To get file inputs into “FormRequest” class I needed to use this code:
LikeLike
Hi, nice post. But how do you handle the rules if every text fields are populated base on the result of database fetch? The field name would be the id of database result
LikeLike
Great write up Eric! I love how much easier this is now with form requests in Laravel 5.
LikeLike
How to validate json array? (bulk items). Thanks
LikeLike
How do manage to put each error near each field? $error->first(‘items.0’) works but what happens if the items are added dynamically?
LikeLiked by 1 person
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? 😀
LikeLike
That is a good question and one I haven’t tested. However, the docs say:
So it seems like you need to just define this:
LikeLike
very useful post. thanks for share 🙂
LikeLike
Hi, good tutorial, my question is if there is a way to put this fields dynamically by using angularjs or jquery button instead a for cycle
LikeLike
The “Book Titled 0” stills seems a little bit vague to the user, will it not be better to insert the value of the index?e.g the “Book Titled Merchant of Venice,,,,,
LikeLike
Hi, good tutorial but I’m stuck on the extra part where only 1 of 4 for fields is required. And I can’t seem to find a way to use the array of form fields with the “required_without_all”.
I currently have this:
As you can see only one of these client number fields is required. But the . notation doesn’t seem to work here..?
Do you have any suggestion for that?
LikeLike
Thank you so much for this short tutorial
LikeLike
Thank you
LikeLike
Thank you so much 🙂
LikeLike
When validation fails, the inputed data are wiped out. I tried using the old() function as an attribute to the input element in blade but it does not work
i.e.
LikeLike
i tried posting a segment of the code, here my 2nd try…
LikeLike
I was referencing it with the square brackets, it should be with a dot notation
LikeLike
Great post!
I have a form with $items[0] to $items[9] and I want a validation rule to check if those values are unique.
Any clue how to solve that?
LikeLike
Not the most pretty, but I guess this works:
public function rules()
{
$products = [];
$rules = [
'name' => 'required|max:255',
];
foreach($this->request->get('product') as $key => $val)
{
$notin = implode(',',$products);
if( $notin != ''):
$rules['product.'.$key] = 'not_in:'.$notin;
endif;
$products[] = $val;
}
return $rules;
}
LikeLike
“namespace AppHttpRequests;” ???? It’s a namespace ?
“use AppHttpRequestsRequest;” ???? and use this namespace ?
It’s a better this :
<?php namespace AppHttpRequests;
use IlluminateHttpRequest;
LikeLike
Thanks. Yeah the slashes got removed when I edited the post. I’ll blame WP for that 🙂 Should be fixed now.
LikeLike
Hi, thank you for the information but it’s not working.
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.
I wonder if my decision to move was wrong..
LikeLike
I just found out that Laravel doesn’t support composite primary key too.. I can do this with Codeigniter, I really regretted migrating to Laravel now that it’s almost finished 😦
LikeLike
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.
LikeLike
I’m trying to validate this:
{!! Form::text(‘text[]’, null, array(‘class’ => ‘form-control’)) !!}
{!! Form::number(‘points[]’, null, array(‘class’ => ‘form-control’)) !!}
So I’ve followed your post and I’m using:
public function rules()
{
$rules = [
// some stuff
];
// validate dynamic choices
foreach ($this->request->get(‘text’) as $key => $val) {
if (!empty($val)) {
$rules[‘text.’ . $key] = ‘required’;
$rules[‘points.’ . $key] = ‘required|integer’;
}
}
return $rules;
}
But when I try to submit a `points` field without value It says this error:
htmlentities() expects parameter 1 to be string, array given
LikeLike
@Paco Orozco
I also got this type error but i change html in your code change into html like text[] to text[0],text[1]…
and point[] to point[1],point[2].. may be your code will working .
LikeLike
thanks
LikeLike
public function rules()
{
// print_r($this->request->get(‘name’));die;
$rules = [
];
foreach($this->request->get(‘name’) as $key => $val)
{
$rules[‘name.’.$key] = ‘required’;
}
foreach($this->request->get(‘quantity’) as $key => $val)
{
$rules[‘quantity.’.$key] = ‘required’;
}
foreach($this->request->get(‘totalprice’) as $key => $val)
{
$rules[‘totalprice.’.$key] = ‘required’;
}
return $rules;
}
I have done ass you said but still same problem as :
ErrorException in helpers.php line 469:
htmlentities() expects parameter 1 to be string, array given (View: \local\resources\views\goods_in\create.blade.php)
LikeLike
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.
LikeLike
hello Eric, thanks for your implication in Laravel ecosystem.
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
group-name[field-name].0 or something else ?
thanks by advance
LikeLike
Thanks Eric. You saved alot
LikeLike
Thanks for this solution
LikeLike
“““““`Your approach doesn’t work properly. I can’t overload custom validation error messages. I get validation error of required, although input fields are filled.
LikeLike
This tutorial is out of date now and only left up for historical reasons. Starting at 5.2 Laravel now includes ways of handling this: https://laravel-news.com/2015/11/laravel-5-2-a-look-at-whats-coming/
LikeLike