Laravel 5.4: Login with Username or Email

I believe that Laravel is now well-known framework among PHP developers. I hope many of you may have already built an application using it. It is really popular due to its powerful features with expressive, beautiful syntax.

From this tutorial, we want to customize the default auth system in our Laravel 5.4 application to allow users to sign in using their username or email address. As of now Laravel framework only supports sign in with email only. After going through this tutorial your application will be able to allow sign in with both username or email, also you can easily extend this concept to any other version of Laravel framework.

 

Before moving to start the tutorial you should be ready with Laravel 5.4 setup on your machine.
Let's begin with creating authentication scaffolding, migrations for User model.

Run below command to generate authentication scaffolding.

php artisan make:auth

If you already have experience with Laravel, then you may know about auth system, which ships with framework out of the box.

If you want to start from scratch, delete the user's table from database/migrations directory and hit the following command to generate new migration file for the user's table.

php artisan make:migration create_users_table --create="users"

Now, we are adding username field to migration file.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('username')->unique();
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Let's migrate the database and go ahead.

php artisan migrate

Now let's look at LoginController.php which implements AuthenticatesUsers.php trait. which also ships with framework out of the box.

If you look at the trait, which includes several methods only related to authenticating the user into the application. Now its time to deal with our actual requirement.

I am going to override the credentials() methods from AuthenticatesUsers.php trait to LoginController.php

Now, my LoginController.php looks like below.

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
     */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest', ['except' => 'logout']);
    }

    /**
     * Get the needed authorization credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function credentials(Request $request)
    {
        $field = filter_var($request->get($this->username()), FILTER_VALIDATE_EMAIL)
            ? $this->username()
            : 'username';

        return [
            $field => $request->get($this->username()),
            'password' => $request->password,
        ];
    }
}

Also, I changed few things in my login.blade.php, the email input field to be the text for username support.

<input type="text" class="form-control" name="email" placeholder="E-Mail / Username" value="{{ old('email') }}" required autofocus>

Okay! now we have a functionality to allow login with username or email.

Last Updated: 10th, September 2017

 

If you would like to view updated new blog post to cover login/register with Laravel v5.5 here.

Conclusion

This tutorial heavily depends on Laravel 5.4, so if you are going to implement this on another version of framework please have a look at the traits used properly to override the credentials array.

Thanks for reading up to the end. If you have any feedback please leave your comments below. Feel free to share with friends if you like it.

Happy Coding!