This tutorial is out of date and no longer maintained.
Today we’ll be creating a simple Laravel authentication. Using migrations, seeding, routes, controllers, and views, we’ll walk through the entire process.
This tutorial will walk us through:
To get our authentication working, we will need to have a database and users to log in with.
Set up your database and user. Assign that user to the database and make sure you update your settings in app/config/database.php
.
Migrations are a way we can manipulate our database within our codebase. This means we don’t have to get our hands dirty by doing any SQL commands or messing around inside a tool like phpmyadmin. For more information and the benefits of migrations, see the official docs.
Migrations are very easy to create. The easiest way to create a migration will be to use the great artisan command-line interface created by Taylor Otwell. To create the migration, via the command line, in the root folder of your application, simply type:
- php artisan migrate:make create_users_table ––create=users
This will automatically create a migrations file inside of your app/database/migrations
folder. Let’s take a look at the newly created file.
// app/database/migrations/####_##_##_######_create_users_table.php
<?php
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;
class CreateUsersTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}
Laravel generates the core of the migration file for you and the --create
command will let the migration create the table for you. It will create a table for you with an id field and the timestamps field. This will make created_at
and updated_at
fields. Now we use the Schema Builder to create our users table.
// app/database/migrations/####_##_##_######_create_users_table.php
<?php
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;
class CreateUsersTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('name', 32);
$table->string('username', 32);
$table->string('email', 320);
$table->string('password', 64);
// required for Laravel 4.1.26
$table->string('remember_token', 100)->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('users');
}
}
Now this migration file will be responsible for creating the users table and also destroying it if needed. To run the migration and create our user table, use the command line again and run:
- php artisan migrate
Just like that, the command will use the up()
function, and bam! We have our users table with all the columns we wanted.
Reverting Migrations: Now if you wanted to rollback migrations, we could use php artisan migrate:rollback
or php artisan migrate:reset
.
Now that we have our table, let’s create sample users.
Seeding is the technique of filling our database with sample data so we can test and create our applications. It really does make building applications much easier. For seeder files, we won’t be using artisan. We’ll make these the good old-fashioned way… New file. In your app/database/seeds
folder, create a file called UserTableSeeder.php
.
// app/database/seeds/UserTableSeeder.php
<?php
class UserTableSeeder extends Seeder
{
public function run()
{
DB::table('users')->delete();
User::create(array(
'name' => 'Chris Sevilleja',
'username' => 'sevilayha',
'email' => 'chris@example.com',
'password' => Hash::make('awesome'),
));
}
}
We will create a user and all of the above is pretty self-explanatory aside from the password. We will use Laravel’s Hash class to create a secure Bcrypt hashing of our password. This is always a good practice to hash our password and to read more about Laravel security, check out the docs. Now that we have created our file, we need Laravel to call it. Inside the app/database/seeds/DatabaseSeeder.php
, add the line $this->call('UserTableSeeder');
.
// app/database/seeds/DatabaseSeeder.php
<?php
class DatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Eloquent::unguard();
$this->call('UserTableSeeder');
}
}
Once we’re done with our seeder file, we can inject that user into our database using:
- php artisan db:seed
Now that we have a database, a table thanks to migrations, and a user thanks to seeding, we can build the authentication system. We will need to create routes, controllers, and views for our form.
In Laravel, our routes file dictates the lay of the land in our application. We will define two routes for our login, one for the HTTP get to show the form, and one for the HTTP post request to process the form. Laravel lets us define routes based on HTTP request types and this helps to organize our application and how a user interacts around the site. For more info on this: show link. Add the following routes we need in our app/routes.php
file:
// app/routes.php
<?php
// route to show the login form
Route::get('login', array('uses' => 'HomeController@showLogin'));
// route to process the form
Route::post('login', array('uses' => 'HomeController@doLogin'));
Now if we go to our application in our browser and go to www.example.com/login, we will get an error because we haven’t defined the HomeController@showLogin function yet. Let’s do that.
In our app/controllers
directory, Laravel should already come with a HomeController.php and a BaseController.php. Inside our HomeController.php, we are going to create the two functions we need. Add these two.
// app/controllers/HomeController.php
...
public function showLogin()
{
// show the form
return View::make('login');
}
public function doLogin()
{
// process the form
}
For now, we will only deal with the function to show the form.
The easiest part of this process will be creating our login view. In the app/views
folder, create a file called login.blade.php
. The .blade.php extension lets Laravel know that we will be using its Blade Templating system.
<!-- app/views/login.blade.php --><
<!doctype html>
<html>
<head>
<title>Look at me Login</title>
</head>
<body><
{{ Form::open(array('url' => 'login')) }}
<h1>Login</h1>
<!-- if there are login errors, show them here -->
<p>
{{ $errors->first('email') }}
{{ $errors->first('password') }}
</p>
<p>
{{ Form::label('email', 'Email Address') }}
{{ Form::text('email', Input::old('email'), array('placeholder' => 'awesome@example.com')) }}
</p>
<p>
{{ Form::label('password', 'Password') }}
{{ Form::password('password') }}
</p>
<p>{{ Form::submit('Submit!') }}</p>
{{ Form::close() }}
When someone submits the form, it posts to the HomeController@doLogin function. Let’s validate the information and process the form.
If there are validation errors, they will be redirected here and the email input will already be filled in with their old input. Errors will also show if there are any.
Back in our HomeController.php, let’s build out our doLogin()
function. We have to validate the information sent to make sure that we have an email and a password. Both fields are required.
// app/controllers/HomeController.php
public function doLogin()
{
// validate the info, create rules for the inputs
$rules = array(
'email' => 'required|email', // make sure the email is an actual email
'password' => 'required|alphaNum|min:3' // password can only be alphanumeric and has to be greater than 3 characters
);
// run the validation rules on the inputs from the form
$validator = Validator::make(Input::all(), $rules);
// if the validator fails, redirect back to the form
if ($validator->fails()) {
return Redirect::to('login')
->withErrors($validator) // send back all errors to the login form
->withInput(Input::except('password')); // send back the input (not the password) so that we can repopulate the form
} else {
// create our user data for the authentication
$userdata = array(
'email' => Input::get('email'),
'password' => Input::get('password')
);
// attempt to do the login
if (Auth::attempt($userdata)) {
// validation successful!
// redirect them to the secure section or whatever
// return Redirect::to('secure');
// for now we'll just echo success (even though echoing in a controller is bad)
echo 'SUCCESS!';
} else {
// validation not successful, send back to form
return Redirect::to('login');
}
}
}
We use the Auth class to authenticate a user. Auth::attempt()
will check the plaintext password against the hashed password we saved in our database.
Try the login: Let’s try to login with whatever we put in our app/database/UserTableSeeder.php
file.
If the authentication is successful (Auth::attempt() returns true), we will redirect the user to wherever they should go. After they are logged in, that user’s information is saved and can be accessed using Auth::user()->email;
. If the authentication is not successful, we will be kicked back to the login form with errors and the old email input to populate the form.
Logging out is a simple matter. We’ll need a new route and a new function.
Add this route for logout.
// app/routes.php
...
Route::get('logout', array('uses' => 'HomeController@doLogout'));
...
Ideally, this route would be a POST
route for security purposes. This will ensure that your logout won’t be accidentally triggered. http://stackoverflow.com/questions/3521290/logout-get-or-post Also, to handle this as a POST
, you will have to handle your link differently. You’ll have to create a POST request to your logout route.
For logout, we will flush and clean out the session and then redirect our user back to the login screen. You can change this to redirect a user wherever you would like. A home page or even a sad goodbye page.
// app/controllers/HomeController.php
public function doLogout()
{
Auth::logout(); // log the user out of our application
return Redirect::to('login'); // redirect the user to the login screen
}
Now that you have the route and the function, you can create a logout button by using the Laravel URL
helper.
<!-- LOGOUT BUTTON -->
<a href="{{ URL::to('logout') }}">Logout</a>
Now going to your login page, www.example.com/login and submitting the login form will provide validation, authentication against a user in the database, and a little more understanding of how Laravel makes things like building an authentication system easier. We’ll be doing a lot more writeups on Laravel, so sound off in the comments if you have questions or anything else you want to see.
Edit Updated the doLogin()
function and the view to pass back errors and handle Auth correctly with Hash::check()
.
Edit #2 Changed back to the Auth::attempt()
login method.
Edit #3 Cleaned up and commented code examples. Provided code for download.
Edit #4 Added logout.
Edit #5 Upgraded user migration to work with Laravel 4.1.26
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.