A quick great tip for you guys. Laravel default authentication allows you to login with an email only but we can also use some other field like username. Laravel by default only allows one field email for login but we can also use username with it as well.
In this tutorial, we will see how we can login with only two fields login and password. Login can either be email or username.
Let’s create a laravel project that allows to login with email or username in one field.
Table of Contents
Setting Up Project
First create a new laravel project named login with laravel installer. We will be using laravel 5.6 in this tutorial.
laravel new login
Setup database credentials in .env
file.
Run the following command to scaffold basic login and registration.
php artisan make:auth
Open create_users_table.php
present in database/migrations
directory. Add the username field in the up
to store the username. To do this, copy the code below and replace it with the up
method.
public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('username'); $table->string('email')->unique(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); }
Now migrate the database by running the following command.
php artisan migrate
Registering Users
After adding username column in the database, it is also required to change laravel default authentication to accept username and save it in the database.
Register View
First let’s add username input field to Users registration form. Go to register.blade.php
present in resources/views/auth
directory. Add the following code after the name row to add a username input 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="username" type="text" class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}" name="username" value="{{ old('username') }}" required> @if ($errors->has('username')) <span class="invalid-feedback"> <strong>{{ $errors->first('username') }}</strong> </span> @endif </div> </div>
The above code is very simple. I have just copied the Name input row and changed the attributes with username.
Full code for register.blade.php
Register Controller
Front end is set up and only the back-end logic is remaining. Go to RegisterController.php
file in app/Http/Controllers/Auth
directory.
In the validator
method, add the validation for the username field as well. Here’s the updated validator method.
protected function validator(array $data) { return Validator::make($data, [ 'name' => 'required|string|max:255', 'username' => 'required|string|max:255|unique:users', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:6|confirmed', ]); }
Username is required, needs to be a string, can contain a maximum of 255 characters and it should be unique in the users table in the username column.
In the create
method, add the username field so that username will also be saved in the database along with other fields. Here’s the updated create
method.
protected function create(array $data) { return User::create([ 'name' => $data['name'], 'username' => $data['username'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); }
Well, we have completely setup username field for the registration.
Log in with username or email
Now that username is added while registering users. Let’s give users the ability to login with either email or username.
Login View
First we need to make some changes to the login view particularly in E-Mail Address input field row. Go to login.blade.php
file present in resources/views/auth
directory. Now replace the first row in the form which the E-Mail Address input field with the contents below.
<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>
Don’t worry, let me explain you everything above. Basically we will send the input of the login with the name login
. Laravel will accept it and it will find either the input is email or username. It will be merged in the request with the key email or username. So, in the value
attribute on input
tag, we are setting it to the old('username')
if it evaluates to true otherwise old('email')
.
We are doing the same when checking for the error. If either username or email is in the errors array we output the respective error.
Full source code for login.blade.php
Login Controller
Let’s setup back-end logic for our login. Go to LoginController.php
file present in app/Http/Controllers/Auth
directory. Here’s the updated code for the Login Controller file.
<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; 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'; /** * Login username to be used by the controller. * * @var string */ protected $username; /** * Create a new controller instance. */ public function __construct() { $this->middleware('guest')->except('logout'); $this->username = $this->findUsername(); } /** * Get the login username to be used by the controller. * * @return string */ public function findUsername() { $login = request()->input('login'); $fieldType = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; request()->merge([$fieldType => $login]); return $fieldType; } /** * Get username property. * * @return string */ public function username() { return $this->username; } }
Let me explain every change made in the Login Controller. We have added a new username property which we will use to store whether the login field is email or username. This field will only have two values email or username. In the constructor, we are calling the findUsername
method. In this method we get the value of the login
input. We check weather the field is a valid email, if yes we set $fieldType
to email
otherwise username
. Then we add the $fieldType
with the input login
in the request by using the merge method. Merge method basically merge a new input into the current request’s array. Then we return the $fieldType
which could either be email
or username
.
The last method we added in the class is the username method. This method is override over the username
method that laravel uses to get the login username to be used.
That’s all what is required to login with email or username in one field.
Find the full source code for the project at GitHub.