Skip to content

gzeinnumer/laravel_login_register_v4

Repository files navigation

laravel_login_register_v4

https://codeanddeploy.com/blog/laravel/laravel-8-authentication-login-and-registration-with-username-or-email

Step 1: Create Laravel App

composer create-project laravel/laravel:^9.0 laravel_login_register_v4
cd laravel_login_register_v4

Step 2: Setup Database Credentials

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_db_name
DB_USERNAME=your_db_username
DB_PASSWORD=your_db_password
Schema::create('users', function (Blueprint $table) {
   $table->id();
   $table->string('name')->nullable();
   $table->string('email')->unique();
   $table->string('username')->unique();
   $table->timestamp('email_verified_at')->nullable();
   $table->string('password');
   $table->rememberToken();
   $table->timestamps();
});

Step 3: Setup Model

  • app/Models/User.php
/**
 * The attributes that are mass assignable.
 *
 * @var array
*/
protected $fillable = [
  'name',
  'email',
  'username',
  'password',
];
/**
 * Always encrypt the password when it is updated.
 *
  * @param $value
 * @return string
 */
public function setPasswordAttribute($value)
{
   $this->attributes['password'] = bcrypt($value);
}

Step 4: Setup Registration Controller

php artisan make:controller RegisterController
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Requests\RegisterRequest;

class RegisterController extends Controller
{
    /**
     * Display register page.
     *
     * @return \Illuminate\Http\Response
     */
    public function show()
    {
        return view('auth.register');
    }

    /**
     * Handle account registration request
     *
     * @param RegisterRequest $request
     *
     * @return \Illuminate\Http\Response
     */
    public function register(RegisterRequest $request)
    {
        $user = User::create($request->validated());

        auth()->login($user);

        return redirect('/')->with('success', "Account successfully registered.");
    }
}

Step 5: Setup Registration Request

php artisan make:request RegisterRequest
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class RegisterRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'email' => 'required|email:rfc,dns|unique:users,email',
            'username' => 'required|unique:users,username',
            'password' => 'required|min:8',
            'password_confirmation' => 'required|same:password'
        ];
    }
}

Step 6: Setup Login Controller

php artisan make:controller LoginController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\LoginRequest;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    /**
     * Display login page.
     *
     * @return Renderable
     */
    public function show()
    {
        return view('auth.login');
    }

    /**
     * Handle account login request
     *
     * @param LoginRequest $request
     *
     * @return \Illuminate\Http\Response
     */
    public function login(LoginRequest $request)
    {
        $credentials = $request->getCredentials();

        if(!Auth::validate($credentials)):
            return redirect()->to('login')
                ->withErrors(trans('auth.failed'));
        endif;

        $user = Auth::getProvider()->retrieveByCredentials($credentials);

        Auth::login($user);

        return $this->authenticated($request, $user);
    }

    /**
     * Handle response after user authenticated
     *
     * @param Request $request
     * @param Auth $user
     *
     * @return \Illuminate\Http\Response
     */
    protected function authenticated(Request $request, $user)
    {
        return redirect()->intended();
    }
}

Step 7: Setup Login Request

php artisan make:request LoginRequest
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;

class LoginRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'username' => 'required',
            'password' => 'required'
        ];
    }

    /**
     * Get the needed authorization credentials from the request.
     *
     * @return array
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function getCredentials()
    {
        // The form field for providing username or password
        // have name of "username", however, in order to support
        // logging users in with both (username and email)
        // we have to check if user has entered one or another
        $username = $this->get('username');

        if ($this->isEmail($username)) {
            return [
                'email' => $username,
                'password' => $this->get('password')
            ];
        }

        return $this->only('username', 'password');
    }

    /**
     * Validate if provided parameter is valid email.
     *
     * @param $param
     * @return bool
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    private function isEmail($param)
    {
        $factory = $this->container->make(ValidationFactory::class);

        return ! $factory->make(
            ['username' => $param],
            ['username' => 'email']
        )->fails();
    }
}

Step 8: Setup Logout Controller

php artisan make:controller LogoutController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;

class LogoutController extends Controller
{
    /**
     * Log out account user.
     *
     * @return \Illuminate\Routing\Redirector
     */
    public function perform()
    {
        Session::flush();

        Auth::logout();

        return redirect('login');
    }
}

Step 9: Setup Home Controller

php artisan make:controller HomeController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller
{
    public function index()
    {
        return view('home.index');
    }
}

Step 10: Setup Routes

<?php

use App\Http\Controllers\HomeController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\LogoutController;
use App\Http\Controllers\RegisterController;
use Illuminate\Support\Facades\Route;


Route::group(['middleware' => ['guest']], function () {
    /**
     * Register Routes
     */
    Route::get('/register', [RegisterController::class, 'show'])->name('register.show');
    Route::post('/register/perform', [RegisterController::class, 'register'])->name('register.perform');

    /**
     * Login Routes
     */
    Route::get('/login', [LoginController::class, 'show'])->name('login.show');
    Route::post('/login', [LoginController::class, 'login'])->name('login.perform');
});

Route::group(['middleware' => ['auth']], function () {
    Route::get('/soon', [HomeController::class, 'index'])->name('soon');

    Route::get('/', [HomeController::class, 'index'])->name('home.index');

    Route::get('/logout', [LogoutController::class, 'perform'])->name('logout.perform');

    Route::prefix('home')->group(function () {
    });
});

Step 11: Setup Our Views

  • resources/views/---layouts/auth-master.blade.php
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="description" content="" />
        <meta
            name="author"
            content="Mark Otto, Jacob Thornton, and Bootstrap contributors"
        />
        <meta name="generator" content="Hugo 0.87.0" />
        <title>Signin Template · Bootstrap v5.1</title>

        <link
            href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css"
            rel="stylesheet"
            integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor"
            crossorigin="anonymous"
        />

        <style>
            .bd-placeholder-img {
                font-size: 1.125rem;
                text-anchor: middle;
                -webkit-user-select: none;
                -moz-user-select: none;
                user-select: none;
            }

            @media (min-width: 768px) {
                .bd-placeholder-img-lg {
                    font-size: 3.5rem;
                }
            }
        </style>

        <!-- Custom styles for this template -->
        <link href="signin.css" rel="stylesheet" />
    </head>

    <body class="text-center d-flex align-items-center justify-content-center vh-100">
        <div class="col-3">
            <main class="form-signin">
                @yield('content')
            </main>
        </div>
    </body>
</html>
  • resources/views/---layouts/app-master.blade.php
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="description" content="" />
        <meta
            name="author"
            content="Mark Otto, Jacob Thornton, and Bootstrap contributors"
        />
        <meta name="generator" content="Hugo 0.87.0" />
        <title>Fixed top navbar example · Bootstrap v5.1</title>

        <link
            href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css"
            rel="stylesheet"
            integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor"
            crossorigin="anonymous"
        />

        <style>
            .bd-placeholder-img {
                font-size: 1.125rem;
                text-anchor: middle;
                -webkit-user-select: none;
                -moz-user-select: none;
                user-select: none;
            }

            @media (min-width: 768px) {
                .bd-placeholder-img-lg {
                    font-size: 3.5rem;
                }
            }
        </style>
    </head>

    <body>
        @include('layouts.partials.navbar')

        <main class="container">@yield('content')</main>

        <script src="{!! url('assets/bootstrap/js/bootstrap.bundle.min.js') !!}"></script>
    </body>
</html>
  • resources/views/---layouts/partials/navbar.blade.php
<header class="p-3 bg-dark text-white">
    <div class="container">
        <div
            class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start"
        >
            <a
                href="/"
                class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none"
            >
                <svg
                    class="bi me-2"
                    width="40"
                    height="32"
                    role="img"
                    aria-label="Bootstrap"
                >
                    <use xlink:href="#bootstrap" />
                </svg>
            </a>

            <ul
                class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0"
            >
                <li>
                    <a href="#" class="nav-link px-2 text-secondary">Home</a>
                </li>
                <li>
                    <a href="#" class="nav-link px-2 text-white">Features</a>
                </li>
                <li>
                    <a href="#" class="nav-link px-2 text-white">Pricing</a>
                </li>
                <li><a href="#" class="nav-link px-2 text-white">FAQs</a></li>
                <li><a href="#" class="nav-link px-2 text-white">About</a></li>
            </ul>

            <form class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3">
                <input
                    type="search"
                    class="form-control form-control-dark"
                    placeholder="Search..."
                    aria-label="Search"
                />
            </form>

            @auth {{ auth()->user()->name }}
            <div class="text-end">
                <a
                    href="{{ route('logout.perform') }}"
                    class="btn btn-outline-light me-2"
                    >Logout</a
                >
            </div>
            @endauth @guest
            <div class="text-end">
                <a
                    href="{{ route('login.perform') }}"
                    class="btn btn-outline-light me-2"
                    >Login</a
                >
                <a
                    href="{{ route('register.perform') }}"
                    class="btn btn-warning"
                    >Sign-up</a
                >
            </div>
            @endguest
        </div>
    </div>
</header>
  • resources/views/---layouts/partials/messages.blade.php
@if (isset($errors) && count($errors) > 0)
<div class="alert alert-warning" role="alert">
    <ul class="list-unstyled mb-0">
        @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
        @endforeach
    </ul>
</div>
@endif @if (Session::get('success', false))
<?php $data = Session::get('success'); ?>
@if (is_array($data)) @foreach ($data as $msg)
<div class="alert alert-warning" role="alert">
    <i class="fa fa-check"></i>
    {{ $msg }}
</div>
@endforeach @else
<div class="alert alert-warning" role="alert">
    <i class="fa fa-check"></i>
    {{ $data }}
</div>
@endif @endif
  • resources/views/---auth/register.blade.php
@extends('layouts.auth-master') @section('content')
<form method="post" action="{{ route('register.perform') }}">
    <input type="hidden" name="_token" value="{{ csrf_token() }}" />
    <img
        class="mb-4"
        src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Bootstrap_logo.svg/1280px-Bootstrap_logo.svg.png"
        alt=""
        width="72"
        height="57"
    />

    <h1 class="h3 mb-3 fw-normal">Register</h1>

    <div class="form-group form-floating mb-3">
        <input
            type="email"
            class="form-control"
            name="email"
            value="{{ old('email') }}"
            placeholder="name@example.com"
            required="required"
            autofocus
        />
        <label for="floatingEmail">Email address</label>
        @if ($errors->has('email'))
        <span class="text-danger text-left">{{ $errors->first('email') }}</span>
        @endif
    </div>

    <div class="form-group form-floating mb-3">
        <input
            type="text"
            class="form-control"
            name="username"
            value="{{ old('username') }}"
            placeholder="Username"
            required="required"
            autofocus
        />
        <label for="floatingName">Username</label>
        @if ($errors->has('username'))
        <span class="text-danger text-left"
            >{{ $errors->first('username') }}</span
        >
        @endif
    </div>

    <div class="form-group form-floating mb-3">
        <input
            type="password"
            class="form-control"
            name="password"
            value="{{ old('password') }}"
            placeholder="Password"
            required="required"
        />
        <label for="floatingPassword">Password</label>
        @if ($errors->has('password'))
        <span class="text-danger text-left"
            >{{ $errors->first('password') }}</span
        >
        @endif
    </div>

    <div class="form-group form-floating mb-3">
        <input
            type="password"
            class="form-control"
            name="password_confirmation"
            value="{{ old('password_confirmation') }}"
            placeholder="Confirm Password"
            required="required"
        />
        <label for="floatingConfirmPassword">Confirm Password</label>
        @if ($errors->has('password_confirmation'))
        <span class="text-danger text-left"
            >{{ $errors->first('password_confirmation') }}</span
        >
        @endif
    </div>

    <button class="w-100 btn btn-lg btn-primary" type="submit">Register</button>

    @include('auth.partials.copy')
</form>
@endsection
  • resources/views/---auth/login.blade.php
@extends('layouts.auth-master') @section('content')
<form method="post" action="{{ route('login.perform') }}">
    <input type="hidden" name="_token" value="{{ csrf_token() }}" />
    <img
        class="mb-4"
        src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Bootstrap_logo.svg/1280px-Bootstrap_logo.svg.png"
        alt=""
        width="72"
        height="57"
    />

    <h1 class="h3 mb-3 fw-normal">Login</h1>

    @include('layouts.partials.messages')

    <div class="form-group form-floating mb-3">
        <input
            type="text"
            class="form-control"
            name="username"
            value="{{ old('username') }}"
            placeholder="Username"
            required="required"
            autofocus
        />
        <label for="floatingName">Email or Username</label>
        @if ($errors->has('username'))
        <span class="text-danger text-left"
            >{{ $errors->first('username') }}</span
        >
        @endif
    </div>

    <div class="form-group form-floating mb-3">
        <input
            type="password"
            class="form-control"
            name="password"
            value="{{ old('password') }}"
            placeholder="Password"
            required="required"
        />
        <label for="floatingPassword">Password</label>
        @if ($errors->has('password'))
        <span class="text-danger text-left"
            >{{ $errors->first('password') }}</span
        >
        @endif
    </div>

    <button class="w-100 btn btn-lg btn-primary" type="submit">Login</button>

    @include('auth.partials.copy')
</form>
@endsection
  • resources/views/---auth/partials/copy.blade.php
<p class="mt-5 mb-3 text-muted">&copy; {{ date('Y') }}</p>
  • resources/views/home/index.blade.php
@extends('layouts.app-master') @section('content')
<div class="bg-light p-5 rounded">
    @auth
    <h1>Dashboard</h1>
    <p class="lead">Only authenticated users can access this section.</p>
    <a
        class="btn btn-lg btn-primary"
        href="https://codeanddeploy.com"
        role="button"
        >View more tutorials here &raquo;</a
    >
    @endauth @guest
    <h1>Homepage</h1>
    <p class="lead">
        Your viewing the home page. Please login to view the restricted data.
    </p>
    @endguest
</div>
@endsection
  • App\Providers\RouteServiceProvider.php
public const HOME = '/home';
public const HOME = '/';
  • App\Http\Middleware\Authenticate
<?php

namespace App\Http\Middleware;

class Authenticate extends Middleware
{
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
            return route('login.show');
        }
    }
}

Step 12: Run The Development Server

php artisan serve
http://127.0.0.1:8000/
http://127.0.0.1:8000/login
http://127.0.0.1:8000/register

Copyright 2023 M. Fadli Zein

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published