Está en la página 1de 18

nput Validation with Laravel

Almost every interactive web application needs to validate data. For instance, a
registration form probably requires the password to be confirmed. Maybe the e-mail
address must be unique. Validations allow you to ensure that only valid data is saved
in the database.
In this lesson, well describe the validation methods available in Laravel and how to
use them effectively. Well also explore how those validation methods interact with
your models attributes and how Laravels built-in error-messaging system can be
used effectively in your applications user interface to provide descriptive feedback.
Validations are used to ensure that the data is of a certain format, type, length, or
value. Some plain English examples of data validation rules would be:
Account usernames must be at least six alpha-numeric characters long and must be
unique.
Marital status must be one of our predefined values (i.e. Married, Unmarried
etc.).
Postal codes must contain only numeric digits.
Validating data can be a cumbersome process. Thankfully, Laravel has a library,
aptly named Validation that will do all the hard work for us and make this mundane
part of programming as simple and as easy as possible.
Why Use Validations?
Why do you need to validate data in the first place? Well, there are a lot times when
it comes in handy:
Data validations are a handy way to ensure that your data is always in a clean and
expected format before it gets into your database. From a programmers point of view,
if you know your data is cleaned and scrubbed, you wont need to write as many
checks and balances or deal with as many potential error-handling procedures. From a
database administrators (DBA) point of view, it also means there is less need for
database checks and procedures to ensure data integrity. And last but not least, from a
users point of view, it usually means a more intuitive experience where typos and
common errors are immediately caught and dealt with.
Validations make your database more secure; potentially harmful data or SQL
injection attacks can be prevented from getting into your database.
Validations help save on band-width and processing; rejecting bad data as early as
possible within the life cycle of your Laravel application saves on resources. There is
no need to involve the expensive call to the database until the data is really ready to be
stored.
Often, business logic is applied to specific data values or types; validations make for
more accurate results and expected execution in these situations.
Validation Approaches
There are several approaches to validate data before it is saved into your database,
including native database constraints, client-side validations, controller-level
validations, and model-level validations. All of these options are discussed below:
Validation Pros Cons
Native
database
constraints
You can use database constraints, triggers, and
stored procedures to validate data. If your
database is used by other applications, especially
if they arent all using Laravel to do so, it may be
a good idea to to move, or at least duplicate, your
critical validations directly inside of the database.
This way all applications are dealing with the
same rules and can reasonably expect the data to
be in the same format regardless of its originating
source. Additionally, database-level validations
can efficiently handle some things (such as
uniqueness of a column in heavily-used tables)
that can be difficult to implement otherwise.
Testing and maintenance is more
difficult. The other big downside to
this approach is that your
validations would be database- and
schema-specific, which makes
migrations or switching to another
database backend more difficult in
the future.
Client-side
validations
If combined with other server-side techniques,
client-side validation can be a convenient way to
provide users with immediate feedback as they
use your site.
Generally unreliable if used alone.
If they are implemented using
JavaScript, they may be bypassed if
JavaScript is turned off in the users
browser.
Validation Pros Cons
Controller-
level
validations Fairly trivial to implement.
Putting too much code inside
controllers makes them unwieldy
and difficult to test and maintain.
Whenever possible, its a good idea
to keep your controllers skinny, as
it will make your application a
pleasure to work with in the long
run.
Model-level
validations
This is the recommended way to ensure that only
valid data is saved into your database. They are
database agnostic, cannot be bypassed by end
users, and are convenient to test and maintain.
Laravel makes model validations easy to use and
provides several built-in helpers for common
needs. You dont need to know any special syntax
or language such as T-SQL or PL/SQL; you just
write Laravel methods with PHP code.
Model validations are only applied
within your Laravel application. If
other applications or programs,
such as Java or Python programs,
access your database, they would
need to do their own data
validations.
Laravel Validation Walk-through
Validating incoming data to make sure data is in accordance to business logic rules
is easy to do in Laravel.
Lets walk through an example application. We will create a tiny Laravel application
to allow users to sign-up with our website. Our application will take information about
the user, validate it and then save it in a database.
Note: Source code for this demo application is available at the github repository
Well begin by creating a database named laravel_validation. Well be using the
MySql database engine for this project. Heres the relevant segment of
my app/config/database.php configuration file:
<?php

return array(
'default' => 'mysql',

'connections' => array(

'mysql' => array(
'driver' => 'mysql',
'host' => '127.0.0.1',
'database' => 'laravel_validation',
'username' => 'Your_Database_Username',
'password' => 'Your_Database_Password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),

...
For this demo app, we only need one table to save user data. Lets create our
users table by leveraging the power of Laravel migrations:
$ php artisan migrate:install
Nice! Now we're ready to do some migrating!

$ php artisan migrate:make create_users_table
Migration created successfully!
Lets open up the new migration file in the app/database/migrations/ folder (mine is
named2013_01_02_074734_create_users_table.php) and paste the following schema
code:
<?php

use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration {

public function up()
{
Schema::create('users', function($t) {
$t->increments('id');
$t->string('real_name', 80);
$t->string('email', 64);
$t->string('password', 64);
$t->integer('age')->nullable();
});
}

public function down()
{
Schema::drop('users');
}

}
The users table schema is not intended to be realistic, but merely to illustrate the use
of validations.
Lets run the migration to create the table in our database:
$ php artisan migrate
Migrated: 2013_01_02_074734_create_users_table
Now, lets create the Laravel model class that relates to this table. We will create a
new PHP file User.php in theapp/models/ folder.
Our User data model will contain the validation logic for newly registered user data.
Lets copy and paste the following code template:
<?php

class User extends Eloquent {

protected $table = 'users';

public $timestamps = false;

public static function validate($input) {
$rules = array(
# place-holder for validation rules
);

# validation code
}

}
Before we can start the validation process we need to create a set of rules that will
be used to validate each attribute of our model. In Laravel rules are defined in an
array format. Lets take a look:
$rules = array(
'real_name' => 'Required|Min:3|Max:80|Alpha',
'email' => 'Required|Between:3,64|Email|Unique:users',
'age' => 'Integer|Min:18',
'password' =>'Required|AlphaNum|Between:4,8|Confirmed',
'password_confirmation'=>'Required|AlphaNum|Between:4,8'
);
The array key is the field that is being validated upon, and the array value contains a
chain of validation rules. In Laravel, we separate the validation rules with the pipe (|)
symbol. Lets taka a closer look:
'real_name' => 'Required|Min:3|Max:80|Alpha',
In this case, we are validating the real_name attribute of our User data model.
The Required rule indicates that the input should not be a blank string. The length of
the users real name must be a minimum of 3 characters (Min:3) and a maximum
length of 80 characters (Max:80). The Alpha rule will check to make sure that
the real_name field only contains alphabets (letters a-z and A-Z).
'email' => 'Required|Between:3,64|Email|Unique:users',
Our email validation rules are similar to the previous one. The Between rule validates
that the length of the email field is within the given range (this is an alternative to
the Min & Max rules described above). The Email rule will check to make sure that the
attribute is a properly formatted e-mail address. The Unique rule validates that an
attribute is unique on a given database table. In the example above,
the email attribute will be checked for uniqueness on the users table.
'age' => 'Integer|Min:18',
Our age field must contain an integer and the value must be at least 18 or greater.
Notice the absence of the Requiredrule because this is an optional field.
'password' =>'Required|AlphaNum|Between:4,8|Confirmed',
'password_confirmation' =>'Required|AlphaNum|Between:4,8'
The AlphaNum rule ensures that the password attribute consists of alphabets and
numbers only. The Confirmed rule ensures that, for a given attribute, a
matching attribute_confirmation attribute exists. It is designed to simplify the process
of confirming two HTML form field values - a common practice for things like
password fields. Your table has one field associated with an attribute, and your
HTML form has two fields that are similar except that one of them has
_confirmation appended to its name. Given the example above, the Validator will
make sure that the passwordattribute matches the password_confirmation attribute in
the array being validated.
An example explains this best:
1. In your HTML form, you need to have something like this:
2. <input type="password" name="password">
3. <input type="password" name="password_confirmation">
4. Now, when the data is submitted to your model, the confirmed rule will check
that the values in these two fields match as part of the validation process. The
validation will succeed if both the fields match.
Dont worry, we will cover all the validation rules later. For now, lets see the
validation in action:
$rules = array(
...
);

$v = Validator::make($input, $rules);
if( $v->passes() ) {
# code for validation success!
} else {
# code for validation failure
}
We create our validator object with the Validator::make() method, passing it our
input array, and our rules array.
if( $v->passes() ) {
# code for validation success!
} else {
# code for validation failure
}
As you can see, we use the passes() method of the Validator object to check the
result of the validation attempt. It returns true if no errors were found in the object
(validation was successful), and false otherwise.
The opposite counter-part to the passes() method is the fails() method which does
just the opposite - it will return true if the validation fails. If you wish, you could
rewrite the above snippet using the fails() method:
if( $v->fails() ) {
# code for validation failure
} else {
# code for validation success!
}
Validation Error Messages
After Validator has performed validations, any errors found can be accessed
through the getMessages() method, which returns a collection of errors. By definition,
an object is valid if this collection is empty after running validations. When your
validation fails, you will want to find out what went wrong. You may access the error
messages via thegetMessages() method to easily retrieve the failed validations.
The Laravel error collector has several simple functions for retrieving your
messages:
if ($v->getMessages()->has('email'))
{
# The e-mail attribute has errors...
}
The has() method determines if an attribute has an error message.
$messages = $v->getMessages()->first('email');
The first() method retrieves the first error message for an attribute. Sometimes you
may need to format the error message by wrapping it in HTML tags. No problem.
Along with the :message place-holder, pass the format as the second parameter to
the method.
$messages = $v->getMessages()->first('email', '<p>:message</p>');
If you want to access all of the error messages for a given attribute, you can call
the get() method:
$messages = $v->getMessages()->get('email');
And if you want to get all of the error messages for all attributes, then you will use
the all() method:
$messages = $v->getMessages()->all();
Both these functions also support custom formatting:
$messages = $v->getMessages()->get('email', '<p>:message</p>');
$messages = $v->getMessages()->all('<p>:message</p>');
Going back to our User model example, lets flesh out the validate() method:
public function validate($input) {

$rules = array(
'real_name' => 'Required|Min:3|Max:80|Alpha',
'email' => 'Required|Between:3,64|Email|Unique:users',
'age' => 'Integer|Min:18',
'password' =>'Required|AlphaNum|Between:4,8|Confirmed',
'password_confirmation'=>'Required|AlphaNum|Between:4,8'
);

return Validator::make($input, $rules);
}
Our validate() function simply returns the Validator object. We can use this object
to check if the validations have succeeded.
For our demo app, we will define two routes:
Route::get('/', function() { });

Route::post('signup', function() { });
The GET / route will display a very simple HTML sign-up form, while the POST
/signup will perform input validation and database-related tasks.
Lets implement the GET / route:
Route::get('/', function() {
return View::make('signup');
});
It simply returns a HTML page.
Heres the corresponding view file app/views/signup.blade.php for the route:
<html>
<body>
<h2>Sign-up Form</h2>
@if ( $errors->count() > 0 )
<p>The following errors have occurred:</p>

<ul>
@foreach( $errors->all() as $message )
<li>{{ $message }}</li>
@endforeach
</ul>
@endif

<form method="POST" action="/signup">

<!-- real name field -->
<p>
<label for="real_name">Real Name (*)</label><br/>
<input type="text" name="real_name" id="real_name">
</p>

<!-- email field -->
<p>
<label for="email">E-mail (*)</label><br/>
<input type="text" name="email" id="email">
</p>

<!-- password field -->
<p>
<label for="password">Password (*)</label><br/>
<input type="password" name="password" id="password">
</p>

<!-- password confirmation field -->
<p>
<label for="password_confirmation">Password (*)</label><br/>
<input type="password" name="password_confirmation"
id="password_confirmation">
</p>

<!-- age field -->
<p>
<label for="age">Age</label><br/>
<input type="text" name="age" id="age">
</p>

<p><small>Fields denoted with an asterisk (*) are mandatory</small></p>

<!-- submit button -->
<p><input type="submit" value="Sign-up"></p>

</form>
</body>
</html>
We are using the $errors->count() method to check if we have any form validation
errors. If we do have any errors, they will be enumerated in the final web page
wrapped inside the <li> HTML tag. Rest of the HTML form is fairly self-explanatory;
all the HTML form fields match our User data model.
This is what the form will look like initially:

.. after validation failure:

Now, lets implement the POST /signup route:
Route::post('signup', function() {
$v = User::validate(Input::all());

if ( $v->passes() ) {
User::create(array(
'real_name'=> Input::get('real_name'),
'email'=> Input::get('email'),
'password'=> Hash::make(Input::get('password')),
'age'=> Input::has('age') ? intval(Input::get('age'))
: null,
));

return 'Thanks for registering!';
} else {
return Redirect::to('/')->withErrors($v->getMessages());
}
});
Lets go through the code quickly:
$v = User::validate(Input::all());
We grab the form submission data using the Input::all() method. We pass this
input data to our User::validate()method to create a new validator object.
if ( $v->passes() ) {
User::create(array(
'real_name'=> Input::get('real_name'),
'email'=> Input::get('email'),
'password'=> Hash::make(Input::get('password')),
'age'=> Input::has('age') ? intval(Input::get('age')) : null,
));

return 'Thanks for registering!';
}
If the validation had passed, we save the user to the database and return the
registration success message.
else {
return Redirect::to('/')->withErrors($v->getMessages());
}
If the validation fails, we redirect back to the sign-up form and flash the validation
errors to the session so they will be available for us to display.
But, notice we did not explicitly bind the errors to the view in our GET / route.
However, an errors variable ($errors) will still be available in the view. Laravel
intelligently determines if errors exist in the session, and if they do, binds them to the
view for you. If no errors exist in the session, an empty message container will still
be bound to the view. In your views, this allows you to always assume you have a
message container available via the errors variable.
Laravel Validation Rules
Below is a list of Laravel validation rules:
Rule Description
Required
Ensure that a value for a field is present, and is not an empty
string.
Alpha Validate that an attribute contains only alphabetic characters.
AlphaNum
Validate that an attribute contains only alphabetic and numeric
characters.
AlphaDash
Validate that an attribute contains only alpha-numeric characters,
dashes, and underscores.
Size:5
[string] The string must be exactly 5 characters
long. [numeric] The value must be 5.
Between:5,10
[string] The length of the string must be between 5 and 10
characters. [numeric] The value must be between 5 and 10.
Min:5
[string] The length of the string must be between 5 characters or
more [numeric] The value must be equal to or greater than
5. [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
5. [numeric] The value must be less than or equal to 5. [file] The
file size must be 5 kilobytes or less.
Numeric The value must be numeric.
Rule Description
Integer The value must be an integer or whole number.
In:small,medium,large
Ensure that the value is contained within the list of values
provided.
NotIn:php,ruby 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_confirmation.
Accepted
The field value must be equal to yes or 1. Useful for validating
checkboxes.
Same:password2 The field value must match the field specified by the same rule.
Different:old_password
The field value must not match the field specified by the same
rule.
Regex:/^([a-z])+$/i The field value must match the provided regular expression.
Unique:users
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 dont occur. If you would like to
specify an alternate column name, simply pass it as a second
parameter:unique:users,email_address. You can also force
the rule to ignore a provided id by passing it as a third
parameter: unique:users,email_address,50. If the primary
key of your table has an alternate column name, you may pass it as
the fourth
parameter:unique:users,email_address,50,alternate_i
d_column_name.
Exists:users,email,john@e
mail.com
Acts as the opposite of Unique, the value must already exist in the
given database table. Yu can pass a second parameter to refer to an
alternate column name:exists:users,email_address
ExistCount:users Get the number of records that exist in database
Before:2012-12-21 Validate that a date attribute is before the given date.
Rule Description
After:1986-05-28 Validate that a date attribute is after the given date.
Ip The value must be a valid IP address.
Email The value must be a valid email address.
Url Validate that an attribute is a URL.
ActiveUrl
Validate that an attribute is an active URL. Note:
The ActiveUrl rule uses checkdnsr to verify the URL is active.
Mimes:jpg,gif
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.
<?php

class BaseModel extends Eloquent
{

public static $validationMessages = null;

public static function validate($input = null) {
if (is_null($input)) {
$input = Input::all();
}

$v = Validator::make($input, static::$rules);

if ($v->passes()) {
return true;
} else {
// save the input to the current session
Input::flash();
self::$validationMessages = $v->getMessages();
return false;
}
}

}

class Gallery extends BaseModel {

public static $rules = array(
# your validation rules here
);

}

También podría gustarte