Please note that this chapter was written for VERSION 3 of the Laravel PHP Framework.
Validation is an important part of many web applications. You can never trust your users, they have been plotting to destroy you for weeks by abusing your forms with evil javascripts.
We can't let them win, they must not destroy our beautiful applications. Let's validate all input provided by the user, that way they won't be able to harm us at all.
Naturally Laravel has a library, aptly named 'Validation' that will do all the hard work for us.
Set up validation
Let's start by creating an imaginary form, close your eyes and imagine a nice long form with many fields... uh oh... how can I get you to open your eyes again..?
Right, I will assume you got fed up of waiting, have opened your eyes and are back with me again, along with our imaginary form. Let's get the input data from that form.
<?php
$input = Input::get();
Now normally you don't want to use the get()
method, as its an easy way to populate your input array with extra data you don't need. In fact the open source collaboration site github was a victim to mass assignment. I have used get()
to simplify the tutorial. In your applications please build the input array only with the fields you need.
Our input array now contains something that looks a little like this..
<?php
array(
'name' => 'John',
'age' => 15
)
Let's validate these fields to make sure they make sense to our application. Before we can start the validation process we need to create a set of rules that will be used to validate each field. With the validator class, rules are defined in an array format. Let's jump right in and take a look.
<?php
$rules = array(
'name' => 'required|min:3|max:32|alpha',
'age' => 'required|integer|min:16'
);
Great, now we have some rules. The array key is the field that is being validated upon, and the array value contains a number of validation rules separate by a pipe | symbol.
In our case we are validating that both fields contain a value by using the 'required' rule. The length of the user's name must be a minimum of 3 characters (min:3) and a maximum length of 32 characters (max:32). The 'alpha' rule will check to make sure that the name field only contains letters.
Our age field must contain an integer
and the value must be at least 16
. You see that the min
rule has adapted to fit the content that its validating, very clever!
Don't worry, we will cover all the validation rules later. For now let's see the validation in action, here we go.
<?php
$v = Validator::make($input, $rules);
We have created our validator object with the make()
method, passing it our input array and our rules array. Let's see if it validates!
<?php
if( $v->fails() )
{
// code for validation failure :(
}
else
{
// code for validation success!
}
As you can see, we use the fails()
method to check the result of the validation attempt, it will return true
if the validation has failed and false
if it was successful.
If you prefer a more positive outlook on your validations, you could use the passes()
method, which returns the opposite values..
<?php
if( $v->passes() )
{
// code for validation success!
}
else
{
// code for validation failure :(
}
There, now we are positive and can dance over rainbows with sparkleponies.
Errors
If your validation fails, which it will because our user is under 16 (sorry for slaying your sparklepony), you will want to find out what went wrong. The validator provides an errors
Messages object which allows us to easily find the information we need.
The errors
object has similar methods to the Input
class, so I will not need to go over them all. Let's retrieve an array of errors for a specific field.
<?php
$age_errors = $v->errors->get('age');
Now we have an array containing all of the errors associated with the age field..
<?php
array(
'The age must be at least 16.'
)
Most of the time I find myself using the first()
method in my views, which returns the first array item if it exists, or null if it doesn't. For example..
<?php echo Form::label('username', 'Username') ?>
<?php echo $errors->first('username') ?>
<?php echo Form::text('username') ?>
Now our validation errors will appear for this field if any are present. You can also pass a second parameter to the first()
method to format the output..
<?php echo $errors->first('username', '<span class="error">:message</span>') ?>
Neat!
You can also use has()
to check to see if an error exists, and all()
to retrieve all errors as an array.
Validation Rules
Here is a list of validation rules, and their purpose.
required
Ensure that a value for a field is present, and is not an empty string.
alpha
The string must only consist of letters (alphabetical characters).
alpha_num
The string must only contain letters and numbers. Useful for usernames.
alpha_dash
The string must contain only letters, numbers, dashes or underscore characters. Useful for storing URL slugs.
size:5
(string) The string must be exactly five characters long. (numeric) The value must be five.
between:5,10
(string) The length of the string must be between five and ten characters. (numeric) The value must be between five and ten.
min:5
(string) The length of the string must be between five characters or more. (numeric) The value must be equal to or greater than five. (file) The file size must be 5 kilobytes or more.
max:5
(string) The length of the string must be less than or equal to five. (numeric) The value must be less than or equal to five. (file) The file size must be 5 kilobytes or less.
numeric
The value must be numeric.
integer
The value must be an integer or whole number.
in:red,green,blue
Ensure that the value is contained within the list of values provided.
not_in:pink,purple
Ensure that none of the values provided match the value.
confirmed
The value of the field must match a confirmation field, named in the format '
accepted
The field value must be equal to 'yes' or 1. Useful for validating check-boxes.
same:age
The field value must match the field specified by the same rule.
different:age
The field value must not match the field specified by the same rule.
match:/[a-z]+/
The field value must match the provided regular expression.
unique:users
This is one of my favourites. The validator will look at the users
database table, and make sure that the value is unique within the column that has the same name as the field name. Useful for making sure that duplicate usernames or email addresses don't occur.
If you would like to specify an alternate column name, simply pass it as a second parameter..
unique:users,nickname
You can also force the rule to ignore a provided id
by passing it as a third parameter.
unique:users,nickname,5
exists:colors
Acts as the opposite of unique
, the value must already exist in the database table. Once more you can pass a second parameter to refer to another column.
before:1984-12-12
The date provided by the field, must have occurred before the date template provided to the before
rule.
The before and after filters use strtotime() to calculate a timestamp for comparison, this means you can do some neat tricks like..
before:next Thursday
Unfortunately I was on the one that added this functionality, so if it breaks you can go ahead and shout at me... sorry!
after:1984-12-12
Similar to before, only the date must occur after the date provided to the after
rule.
The value must be a valid email address.
url
The value must match the format of an URL.
active_url
The value must match a valid active URL. checkdnsr
is used to verify that the URL is active.
mimes:png,mp3
The value must be a $_FILE
which whose MIME type matches the file extensions provided.
You can add additional MIME types to the array in config/mimes.php
.
image
The uploaded file must be an image.
Custom Error Messages
I find the default error messages quite descriptive, but your clients might have their own ideas. Let's see how we can customize our error messages to suit our needs.
You can edit the validation error messages directly by modifying the file application/language/en/validation.php
...
...
"after" => "The :attribute must be a date after :date.",
"alpha" => "The :attribute may only contain letters.",
"alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.",
...
Laravel replaces the :attribute
marker with the name of the field. Other markers also exist within the rules, and their purpose is quite self explanatory.
If you would rather change the messages for a single form, rather than edit them globally, you can pass a third array of messages to the Validator::make()
method.
<?php
$messages = array(
'same' => 'The :attribute and :other must match, fool!',
'size' => 'The :attribute must be exactly :size , like duh!'
);
$v = Validator::make($input, $rules, $messages);
Great now we have custom messages! We can even specify error messages for individual fields by setting the message key to field_rule
, for example..
<?php
$messages = array(
'age_required' => 'You need to have had at least one birthday!'
);
Custom Validation Rules
The validator allows you add extra rules to suit the needs of your application, let's jump right in and take a look at how we register a new validation rule.
<?php
Validator::register('superdooper', function($attribute, $value, $parameters){
return $value == 'superdooper';
});
Our newly created validation rule superdooper
will ensure that our value matches the string 'superdooper'. Your custom validations should return true
on success, or false
on failure.
The $attribute
value will be the name of the field being validated, and $value
will of course contain the value.
The $parameters
attribute contains an array of parameters that have been passed to the rule after the colon, and separated by commas.
As you have created a new validator, there will be no error messages associated with it yet, we will need to add one so that Laravel knows what to say when it fails. We can add an error message in the same way as we have previously..
<?php
'superdooper' => 'The :attribute must be superdooper, ok trooper?!',
Once again you can pass the extra error message array as a third parameter to the Validator::make()
method, or simply add it to your application/language/en/validation.php
file for safe keeping.
Validation Classes
If we want to provide many new validation methods, or reuse them across a number if projects, it would be best to create a validation class. Validation classes extend Laravel's data, and overload it with additional validation methods. The class is created in the application/libraries
directory for easy loading, but you could place it elsewhere as long as it is registered with the Autoloader
(later chapter). Let's take a look at the class.
<?php
// application/libraries/validator.php
class Validator extends Laravel\Validator {
public function validate_awesome($attribute, $value, $parameters)
{
return $value == 'awesome';
}
}
As you can see our Validator class extends the Laravel\Validator
name-spaced core class and provides additional validations in the form of validate_<rulename>
methods. The validation methods accept the same parameters as the Validator::register()
closure, and work in the same way.
In order to use our new validation class, we will need to remove the existing alias for Validator
from our application/config/application.php
file. This way Laravel will use our created class instead of the one in the Laravel source folder.
You could use this method to replace the original validation methods with your own, for example you could create a validate_size
method and calculate the size in an alternate format.
I would suggest adding custom error messages to the validation language file when using Validation classes, this will allow for a much easier migration to another project, and will not require any 'source-digging' to find all the messages used.
My books are available online for free to encourage learning. However, if you'd like for me to keep writing, then please consider buying a digital copy over at Leanpub.com.
It's available in PDF, ePub, and Kindle format, and contains a bunch of extras that you won't find on the site. I have a full-time job, and I write my books in my spare time. Please consider buying a copy so that I can continue to write new books from the comfort of my sofa!