Laravel 9 tutorial, create login form using middleware on PPDB Project part 1
On this project, we used laravel 9.x to build PPDB App. This project also available on github and our youtube channel.
The Laravel framework has a few system requirements. You should ensure that your web server has the following minimum PHP version and extensions:
- PHP >= 8.0
- BCMath PHP Extension
- Ctype PHP Extension
- cURL PHP Extension
- DOM PHP Extension
- Fileinfo PHP Extension
- JSON PHP Extension
- Mbstring PHP Extension
- OpenSSL PHP Extension
- PCRE PHP Extension
- PDO PHP Extension
- Tokenizer PHP Extension
- XML PHP Extension
Install Laravel 9
Install laravel 9.x via composer
composer create-project laravel/laravel ppdb
Setting .ENV File
Open laravel project using text editor and update .ENV file, we create APP_NAME and database configuration.
Make sure you have created "ppdb_youtube" database from PhpMyadmin.
Migrations
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('username',50)->unique();
$table->string('email',50)->unique();
$table->string('password');
$table->smallInteger('level')->default(1)->comment('1=user, 2=pengawas, 3=administrator');
$table->rememberToken();
$table->timestamps();
});
}
User Model
protected $fillable = [
'username',
'email',
'password',
'level',
];
Seeders
public function run()
{
// \App\Models\User::factory(10)->create();
DB::table('users')->insert([
'username' => 'admin',
'email' => Str::random(10).'@gmail.com',
'password' => Hash::make('admin'),
'level'=> 3,
'remember_token'=> Str::random(60),
'created_at' => now()
]
);
DB::table('users')->insert([
'username' => 'pengawas',
'email' => Str::random(10).'@gmail.com',
'password' => Hash::make('pengawas'),
'level'=> 2,
'remember_token'=> Str::random(60),
'created_at' => now()
]
);
DB::table('users')->insert([
'username' => 'user',
'email' => Str::random(10).'@gmail.com',
'password' => Hash::make('user'),
'level'=> 1,
'remember_token'=> Str::random(60),
'created_at' => now()
]
);
}
Run seeder using this command
php artisan db:seed
Login Controller
class LoginController extends Controller
{
public function showLogin()
{
// cek if user has logged
if (Auth::check()) {
return redirect(route('dashboard'));
}
// if not ..
return view('login')->with('error',0);
}
public function processLogin(Request $request)
{
// cek username and passowrd
if (Auth::attempt($request->only('username','password'))){
// login success
return redirect(route('dashboard'));
}
// incorrect login
return redirect(route('login'))->with('error',1);
}
public function processLogout(Request $request)
{
Auth::logout();
return redirect('/');
}
}
Dashboard Controller
public function index(){
return view('dashboard');
}
Routes
Route::get('/login', [LoginController::class, 'showLogin'])->name('login');
Route::post('/processLogin', [LoginController::class,'processLogin'])->name('processLogin');
Route::get('/processLogout', [LoginController::class,'processLogout'])->name('processLogout');
Route::group(['middleware' => ['auth', 'level:3,2']], function(){
Route::get('/dashboard', [DashboardController::class,'index'])->name('dashboard');
});
Login Blade
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{config('app.name')}} - Login</title>
<link rel="shortcut icon" href="{{asset('favicon.ico')}}">
<!-- plugin css -->
<link href="{{asset('css/iconfont.css')}}" rel="stylesheet" />
<link href="{{asset('css/perfect-scrollbar.css')}}" rel="stylesheet" />
<!-- end plugin css -->
<link href="{{asset('css/prism.css')}}" rel="stylesheet" />
<!-- common css -->
<link href="{{asset('css/app.css')}}" rel="stylesheet" />
<!-- end common css -->
</head>
<body data-base-url="/">
<div class="main-wrapper" id="app">
<div class="page-wrapper full-page">
<div class="page-content d-flex align-items-center justify-content-center">
<div class="row w-100 mx-0 auth-page">
<div class="col-md-8 col-xl-6 mx-auto">
<div class="card">
<div class="row">
<div class="col-md-4 pe-md-0">
<div class="auth-side-wrapper" style="background-image: url({{asset('img/bg-login.jpg')}})"></div>
</div>
<div class="col-md-8 ps-md-0">
<div class="auth-form-wrapper px-4 py-5">
<a href="{{route('login')}}" class="noble-ui-logo d-block mb-2">{{config('app.name')}}</a>
<h5 class="text-muted fw-normal mb-4">Welcome back! Log in to your account.</h5>
<form action="{{route('processLogin')}}" class="forms-group" method="post">
{{ csrf_field() }}
@if(session('error') ==1)
<div class="alert alert-danger">
Ouuuppssss... incorrect username or password, please try again!
</div>
@endif
<div class="mb-3">
<label for="username" class="form-label text-muted">Username<span class="text-danger">*</span></label>
<input type="text" class="form-control" name="username" id="username" placeholder="Enter your username">
</div>
<div class="mb-3">
<label for="password" class="form-label text-muted">Password<span class="text-danger">*</span></label>
<input type="password" class="form-control" name="password" id="password" autocomplete="current-password" placeholder="Enter your password">
</div>
<div>
<button type="submit" class="btn btn-sm btn-info me-2 mb-2">
<i class="btn-icon-prepend" data-feather="unlock"></i>
Login
</button>
</div>
<a href="#" class="d-block mt-3 text-muted">Not a user? Sign up</a>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="{{asset('js/spinner.js')}}"></script>
<!-- base js -->
<script src="{{asset('js/app.js')}}"></script>
<script src="{{asset('js/feather.min.js')}}"></script>
<script src="{{asset('js/perfect-scrollbar.min.js')}}"></script>
<!-- end base js -->
<!-- plugin js -->
<script src="{{asset('js/prism.js')}}"></script>
<script src="{{asset('js/clipboard.min.js')}}"></script>
<!-- end plugin js -->
<!-- common js -->
<script src="{{asset('js/template.js')}}"></script>
<!-- end common js -->
</body>
</html>
Dashboard Blade
@extends('templates.master')
@section('content')
<div class="row">
<h2>Wellcome {{\Illuminate\Support\Facades\Auth::user()->username}}</h2>
</div>
@endsection
/templates/master.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{config('app.name')}} - Administrator</title>
<link rel="shortcut icon" href="{{asset('favicon.ico')}}">
<!-- plugin css -->
<link href="{{asset('css/iconfont.css')}}" rel="stylesheet" />
<link href="{{asset('css/perfect-scrollbar.css')}}" rel="stylesheet" />
<!-- end plugin css -->
<link href="{{asset('css/prism.css')}}" rel="stylesheet" />
<!-- common css -->
<link href="{{asset('css/app.css')}}" rel="stylesheet" />
<!-- end common css -->
</head>
<body data-base-url="/">
<script src="{{asset('js/spinner.js')}}"></script>
<div class="main-wrapper" id="app">
<nav class="sidebar">
<div class="sidebar-header">
<a href="{{route('dashboard')}}" class="sidebar-brand">
PPDB<span>App</span>
</a>
<div class="sidebar-toggler not-active">
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class="sidebar-body">
@include('templates.left_menu')
</div>
</nav>
<div class="page-wrapper">
<nav class="navbar">
<a href="#" class="sidebar-toggler">
<i data-feather="menu"></i>
</a>
<div class="navbar-content">
@include('templates.top_menu')
</div>
</nav>
<div class="page-content">
@yield('content')
</div>
<footer class="footer d-flex flex-column flex-md-row align-items-center justify-content-between px-4 py-3 border-top small">
<p class="text-muted mb-1 mb-md-0">Copyright © {{now()->format('Y')}} <a href="javascript:void(0);">PPDB App</a>.</p>
<p class="text-muted">Handcrafted With <i class="mb-1 text-primary ms-1 icon-sm" data-feather="heart"></i></p>
</footer>
</div>
</div>
<!-- base js -->
<script src="{{asset('js/app.js')}}"></script>
<script src="{{asset('js/feather.min.js')}}"></script>
<script src="{{asset('js/perfect-scrollbar.min.js')}}"></script>
<!-- end base js -->
<!-- plugin js -->
<script src="{{asset('js/prism.js')}}"></script>
<script src="{{asset('js/clipboard.min.js')}}"></script>
<!-- end plugin js -->
<!-- common js -->
<script src="{{asset('js/template.js')}}"></script>
<!-- end common js -->
</body>
</html>
/templates/left_menu.blade.php
<ul class="nav">
<li class="nav-item nav-category">Main</li>
<li class="nav-item ">
<a href="{{route('dashboard')}}" class="nav-link">
<i class="link-icon" data-feather="box"></i>
<span class="link-title">Home</span>
</a>
</li>
<li class="nav-item nav-category">Master Data</li>
<li class="nav-item ">
<a class="nav-link" data-bs-toggle="collapse" href="#users" role="button" aria-expanded="false">
<i class="link-icon" data-feather="users"></i>
<span class="link-title">Users</span>
<i class="link-arrow" data-feather="chevron-down"></i>
</a>
<div class="collapse " id="users">
<ul class="nav sub-menu">
<li class="nav-item">
<a href="#" class="nav-link">Biodata</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">Akun</a>
</li>
</ul>
</div>
</li>
<li class="nav-item ">
<a href="#" class="nav-link">
<i class="link-icon" data-feather="archive"></i>
<span class="link-title">Program Studi</span>
</a>
</li>
<li class="nav-item ">
<a href="#" class="nav-link">
<i class="link-icon" data-feather="archive"></i>
<span class="link-title">Bidang Studi</span>
</a>
</li>
<li class="nav-item ">
<a href="#" class="nav-link">
<i class="link-icon" data-feather="printer"></i>
<span class="link-title">Laporan</span>
</a>
</li>
</ul>
/templates/top_menu.blade.php
<form class="search-form">
<div class="input-group">
<div class="input-group-text">
<i data-feather="search"></i>
</div>
<input type="text" class="form-control" id="navbarForm" placeholder="Search here...">
</div>
</form>
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="profileDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img class="wd-30 ht-30 rounded-circle" src="{{asset('img/bg-login.jpg')}}" alt="profile">
</a>
<div class="dropdown-menu p-0" aria-labelledby="profileDropdown">
<div class="d-flex flex-column align-items-center border-bottom px-5 py-3">
<div class="mb-3">
<img class="wd-80 ht-80 rounded-circle" src="{{asset('img/bg-login.jpg')}}" alt="">
</div>
<div class="text-center">
<p class="tx-16 fw-bolder">{{\Illuminate\Support\Facades\Auth::user()->username}}</p>
<p class="tx-12 text-muted">{{\Illuminate\Support\Facades\Auth::user()->email}}</p>
</div>
</div>
<ul class="list-unstyled p-1">
<li class="dropdown-item py-2">
<a href="{{route('processLogout')}}" class="text-body ms-0">
<i class="me-2 icon-md" data-feather="log-out"></i>
<span>Log Out</span>
</a>
</li>
</ul>
</div>
</li>
</ul>
Video Tutorial
This project available on Github
COMMENTS