Laravel login using username or email

Laravel comes with their own auth system, so you don’t have to build login, registration, and authentication system from scratch.

By default, Laravel uses email for authentication. If you want to use username, you have to make little tweak to your controller as explained in their documentation.

But, what if you want to use either email or username for authentication? In this post, I’ll show you how to do that.

Setup Project

Open your terminal or command prompt, enter this command. Wait until installation is done.

laravel new login --auth

For simplicity, we use SQLite for database. Change lines in .env from

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

to this

DB_CONNECTION=sqlite

Add empty file in directory database/. Name it database.sqlite.

Login by username

Open xxxx_xx_xx_create_users_table.php located in database/migrations. Add username field in our users table. Make sure username field is unique.

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->string('username')->unique(); //new field
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

Migrate database by using this command.

php artisan migrate

Open registration view in resources/views/auth/register.blade.php. We need a way to insert our new field username in user registration. Add this code between user & email field.

<div class="form-group row">
    <label for="username" class="col-md-4 col-form-label text-md-right">{{ __('Username') }}</label>

    <div class="col-md-6">
        <input id="email" type="username" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autocomplete="username">

        @error('username')
            <span class="invalid-feedback" role="alert">
                <strong>{{ $message }}</strong>
            </span>
        @enderror
    </div>
</div>

We need to change Laravel authentication from email to username. Open LoginController located in app/Http/Controllers/Auth/LoginController.php. Then, add following method in that file.

public function username()
{
    return 'username';
}

Next step is to modify RegisterController to validate username field. Add username validator.

protected function validator(array $data)
{
    return Validator::make($data, [
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
        'password' => ['required', 'string', 'min:8', 'confirmed'],
        'username' => ['required', 'string', 'max:255', 'unique:users'], //new validator
    ]);
}

And add following code in create method.

protected function create(array $data)
{
    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
        'username' => $data['username'], //new field
    ]);
}

Don’t forget to add username in fillable variable on app/User.php.

protected $fillable = [
    'name', 'email', 'password', 'username'
];

Open login view in resources/views/auth/login.blade.php. Change email field to username with following code.

<div class="form-group row">
    <label for="username" class="col-md-4 col-form-label text-md-right">{{ __('Username') }}</label>

    <div class="col-md-6">
        <input id="username" type="username" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autocomplete="username" autofocus>

        @error('username')
            <span class="invalid-feedback" role="alert">
                <strong>{{ $message }}</strong>
            </span>
        @enderror
    </div>
</div>

You can test it, by command php artisan serve. Register and login.

If you just need to your web to login by username, you can stop right here. But, if you need to login by username or email, let’s continue to the next step.

Login by username or email

Open login view again. Then, change previous code we made on username field, so user can input email or username.

<div class="form-group row">
    <label for="login" class="col-sm-4 col-form-label text-md-right">
        {{ __('Username or Email') }}
    </label>

    <div class="col-md-6">
        <input id="login" type="text"
                class="form-control{{ $errors->has('username') || $errors->has('email') ? ' is-invalid' : '' }}"
                name="login" value="{{ old('username') ?: old('email') }}" required autofocus>

        @if ($errors->has('username') || $errors->has('email'))
            <span class="invalid-feedback">
                <strong>{{ $errors->first('username') ?: $errors->first('email') }}</strong>
            </span>
        @endif
    </div>
</div>

Basically, we want to send login request instead of username. On LoginController we will check this request and decide which method we use, base on text format. If it’s in email, check login with email, if it’s not email format use username.

Open LoginController again, add this global variable.

protected $fieldToCheck;

Change method username(), return it with new global variable.

public function username()
{
    return $this->fieldToCheck;
}

Updated construct method with this.

public function __construct()
{
    $this->middleware('guest')->except('logout');

    $login = request()->input('login');

    //if user input is in email format, use email
    if (filter_var($login, FILTER_VALIDATE_EMAIL)){
        $this->fieldToCheck = "email";
    } else {
        $this->fieldToCheck = "username";
    }

    request()->merge([
        $this->fieldToCheck => $login //add new field to existing request
    ]);

}

That’s it. We are done. You can login using username or email. If you need help, leave questions on comment section!

Full project in on my github here -> https://github.com/rifai/laravel-login

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.