Form array validation in Laravel 5.2
This is a series of posts on New Features in Laravel 5.2.
!Warning: This post is over a year old. I don't always update old posts with new information, so some of this information may be out of date.
It's time to start writing about the new features in Laravel 5.2! You'll notice that many of these features are quicker and easier to learn and write up, so it may seem that it's a smaller release. But many of the features in 5.2 will have a big impact on the simplicity and convenience of the code we write day-to-day.
A quick introduction to HTML Form arrays
Form array validation simplifies the process of validating the somewhat abnormal shape of data HTML forms pass in when the array syntax is used. If you're not familiar with it, a common use case is when you allow a user to add multiple instances of the same type on one form.
Let's imagine you have a form where a user is adding a company, and as a part of it they can add as many employees to the company as they want. Each employee has a name and a title.
Here's our HTML; imagine that we have some JavaScript that creates a new "employee" div every time you press the "Add another employee" button so they user can add as many employees they want.
<form>
<label>Company Name</label>
<input type="text" name="name">
<h3>Employees</h3>
<div class="add-employee">
<label>Employee Name</label>
<input type="text" name="employee[1][name]">
<label>Employee Title</label>
<input type="text" name="employee[1][title]">
</div>
<div class="add-employee">
<label>Employee Name</label>
<input type="text" name="employee[2][name]">
<label>Employee Title</label>
<input type="text" name="employee[2][title]">
</div>
<a href="#" class="js-create-new-add-employee-box">Add another employee</a>
<input type="submit">
</form>
````
If you fill out that form and submit it, this is the shape of the `$_POST`:
array(2) { ["name"]=> string(10) "Acme, Inc." ["employee"]=> array(2) { [1]=> array(2) { ["name"]=> string(10) "Joe Schmoe" ["title"]=> string(11) "Head Person" } [2]=> array(2) { ["name"]=> string(18) "Conchita Albatross" ["title"]=> string(21) "Executive Head Person" } } }
As you can see, we get an `employee` "object". And it contains an array of the IDs that we passed in, with the key/value pairs of "fieldname" => "user provided field value".
> Note: It used to be common to just set every instance of the "employee name" field, for example, to be just `employee[][name]` without setting the ID manually. *Don't do this.* It'll make every aspect of working with the code more complex.
But how do we validate this? Prior to 5.2, it's a bunch of manual work. Now, Laravel understands this nesting structure and can validate against it uniquely.
## Writing form array validation rules
So, how do we do it? Let's take a look at a normal validator:
```php
// CompaniesController.php
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|string'
]);
// Save, etc.
}
And now let's add validation for our company employee fields:
// CompaniesController.php
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|string',
'employee.*.name' => 'required|string',
'employee.*.title' => 'string',
]);
// Save, etc.
}
Now we're validating every employee[*][name]
and employee[*][title]
uniquely, with pretty much no effort on our part. Beautiful.
Postscript
You may have noticed that the shape of the validation is employee.*.name
, with an asterisk in the middle, which almost indicates that you could put something else there.
What if, instead of an asterisk to indicate "all", you put a specific number there? Turns out it'll only validate the entities with that ID. So if you put employee.1.name
in the validation array instead of employee.*.name
, only the employee with the ID of 1
will be validated according to those rules.
I don't know why or when you would do it, but you could actually set completely separate validation rules for each ID:
$this->validate($request, [
'employee.1.name' => 'required|string',
'employee.2.name' => 'integer', // Not sure *why* you would do this, but, it's possible
]);
That's it. Enjoy!
Comments? I'm @stauffermatt on Twitter
Tags: laravel • laravel 5.2
This is part of a series of posts on New Features in Laravel 5.2:
-
Dec 17, 2015 | laravel, laravel 5.2
-
Dec 18, 2015 | laravel, laravel 5.2
-
Dec 19, 2015 | laravel, laravel 5.2, API
-
Dec 22, 2015 | laravel, laravel 5.2, middleware
-
Jan 8, 2016 | laravel, laravel 5.2
-
Jan 22, 2016 | laravel, laravel 5.2, authentication