Creating custom login using laravel

In this post, we will be drawing out snippets required for implementing custom login without scaffolding step by step in laravel.

If you follow these steps implementation of this feature will be completed quickly. But before going through steps here you need to implement custom registration first illustrated in this link.

Step 01: Setting up routes/web.php

// at the top 
use App\Http\Controllers\LoginController;

Route::controller(LoginController::class)->group(function () {
    Route::get('/login', 'index')->name('login');
    Route::post('/login', 'login');
});


Step 02:
Setting up LoginController with validation

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class LoginController extends Controller
{
    
    public function index()
    {
        return view('auth.login');
    }

    public function login(Request $request) 
    { 
        $this->validate($request, [
            'email' => 'required',
            'password' => 'required',
        ]); 

        $fieldType = filter_var($request->email, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';

        if( !auth()->attempt(array( $fieldType => $request->email , 'password' => $request->password ))) {
            return redirect()->route( 'login' )->with('error', 'Invalid login details');
        }
        
        return redirect()->route('dashboard');
    }
}


Step 03:
Setting up login.blade.php under resource/auth folder

@extends('app')
@section('content')
@include('flash-message') 
<div class="card">    
    <div class="card-header">
        Site Login
    </div>
    <div class="card-body">
        <form method="post" action="{{ route('login') }}" id="updatefrm" method="post" enctype="multipart/form-data">
            @csrf
            <div class="form-group">              
                <label for="title">Username or Email</label>  <br>    
                <input name="email" class="form-control" placeholder="Username or Email" 
                                    title="email" maxlength="25" type="text" id="email" value="{{ old('email') }}"/>
                @if ($errors->has('email'))
                    <span class="text-danger">{{ $errors->first('email') }}</span>
                @endif                                                           
            </div> 
            <div class="form-group">
                <label for="title">Password</label>  <br>    
                <input name="password" class="form-control" placeholder="Password, must be between 5 - 20 characters" title="password" type="password" id="UserPassword" required="required"/>
                @if ($errors->has('password'))
                    <span class="text-danger">{{ $errors->first('password') }}</span>
                @endif                                                           
            </div>           
            <input class="btn btn-info" class="form-control" type="submit"  name="action" value="Login" >
        </form>	
    </div>
</div>  
@endsection


Step 04:
Changing some html in dashboard.blade.php under resource/auth folder from registration post

@extends('app')
@section('content')
<div class="card">
    @include('flash-message') 
    <div class="card-header">
        Site Dashboard
    </div>    
    <div class="card-body">
        <p>
        Welcome to Site dashboard 
        </p>
        <p>
            <label>Username: </label> <strong>{{ auth()->user()->username }}</strong>
        </p>
        <p>
        <label>Name: </label> <strong>{{ auth()->user()->name }}</strong>
        </p>
        <p>
        <label>Email: </label> <strong>{{ auth()->user()->email }}</strong>
        </p>
        <p>
        <label>Gender: </label> <strong>{{ auth()->user()->gender }}</strong>
        </p>
    </div>    
</div>  
@endsection


Step 05:
Using currentRouteName from Route facade to make urls dynamically active when browsed in app.blade.php

<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
	<ul class="navbar-nav">
	  <li class="nav-item {{ in_array(Route::currentRouteName(),['signup']) ? 'active': '' }}">
		<a class="nav-link " href="{{ route('signup') }}">Home</a>
	  </li>
	  @guest
	  <li class="nav-item {{ in_array(Route::currentRouteName(),['login']) ? 'active': '' }}">
		<a class="nav-link " href="{{ route('login') }}">Login</a>
	  </li>  
	  @endguest                    
	  @auth
	  <li class="nav-item {{ in_array(Route::currentRouteName(),['dashboard']) ? 'active': '' }}">
		<a class="nav-link " href="{{ route('dashboard') }}">Dashboard</a>
	  </li>
	  <li class="nav-item">
		<a class="nav-link" href="{{ route('logout') }}">Logout</a>
	  </li>                      
	  @endauth
	</ul>
</nav>


Step 06:
Back in LoginController adding constructor method with guest middleware to prevent accessing login page after user login is successful

public function __construct()
{
   $this->middleware(['guest']);
}


Step 07:
Tweaking configuation in RouteServiceProvider.php for default login redirection ( after login if login page is browsed )

public const HOME = '/';