Kritim Yantra
Feb 28, 2025
In this blog post, we'll walk through creating a login system in Laravel 12 that supports both admin and user roles using separate database tables. This approach is useful when you need distinct authentication logic or different sets of permissions for admins and regular users. By the end, you'll have a fully functional login system with separate login forms and protected routes for each role.
If you're new to Laravel, don’t worry—I’ll explain each step in detail.
Create a new Laravel project using Composer:
composer create-project laravel/laravel blog-login-system "12.*"
Then navigate into your project directory:
cd blog-login-system
Create a new database in your MySQL server (e.g., blog_login_db
). Then, update the .env
file with your database credentials:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog_login_db
DB_USERNAME=root
DB_PASSWORD=
Replace root
and the empty password with your actual database username and password.
Laravel comes with a User
model and migration by default. We’ll use this for regular users and create a separate Admin
model and migration for admins.
The default users
table migration is located in database/migrations/xxxx_xx_xx_xxxxxx_create_users_table.php
. It should include fields like id
, name
, email
, password
, and timestamps.
Run the following command to create the Admin
model and its migration:
php artisan make:model Admin -m
This generates two files:
app/Models/Admin.php
database/migrations/xxxx_xx_xx_xxxxxx_create_admins_table.php
Update the admins migration to define the table structure:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAdminsTable extends Migration
{
public function up()
{
Schema::create('admins', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('admins');
}
}
Run the migrations to create the users
and admins
tables:
php artisan migrate
We’ll manually set up authentication for users using Laravel’s built-in features.
Create a LoginController
for users in app/Http/Controllers/Auth/LoginController.php
:
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
Create the login view for users at resources/views/auth/login.blade.php
:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Login') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('login') }}">
@csrf
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
In routes/web.php
, add the following routes for user authentication:
use App\Http\Controllers\Auth\LoginController;
Route::get('login', [LoginController::class, 'showLoginForm'])->name('login');
Route::post('login', [LoginController::class, 'login']);
Route::post('logout', [LoginController::class, 'logout'])->name('logout');
To handle admin authentication separately, we’ll create a new guard and a login controller for admins.
Open config/auth.php
and update the guards
and providers
sections:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
Create app/Http/Controllers/Auth/AdminLoginController.php
:
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminLoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/admin/dashboard';
public function __construct()
{
$this->middleware('guest:admin')->except('logout');
}
public function showLoginForm()
{
return view('auth.admin-login');
}
protected function guard()
{
return Auth::guard('admin');
}
public function logout(Request $request)
{
Auth::guard('admin')->logout();
return redirect('/admin/login');
}
}
Create resources/views/auth/admin-login.blade.php
with a similar form to the user login:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Admin Login') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('admin.login') }}">
@csrf
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Add the following routes in routes/web.php
:
use App\Http\Controllers\Auth\AdminLoginController;
Route::get('admin/login', [AdminLoginController::class, 'showLoginForm'])->name('admin.login');
Route::post('admin/login', [AdminLoginController::class, 'login']);
Route::post('admin/logout', [AdminLoginController::class, 'logout'])->name('admin.logout');
We’ll create simple dashboard views for both users and admins, protected by their respective authentication guards.
Create app/Http/Controllers/HomeController.php
:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
public function index()
{
return view('home');
}
}
Create resources/views/home.blade.php
:
@extends('layouts.app')
@section('content')
<div class="container">
<h1>Welcome, User!</h1>
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit" class="btn btn-danger">Logout</button>
</form>
</div>
@endsection
Create app/Http/Controllers/AdminController.php
:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AdminController extends Controller
{
public function dashboard()
{
return view('admin.dashboard');
}
}
Create resources/views/admin/dashboard.blade.php
:
@extends('layouts.app')
@section('content')
<div class="container">
<h1>Welcome, Admin!</h1>
<form action="{{ route('admin.logout') }}" method="POST">
@csrf
<button type="submit" class="btn btn-danger">Logout</button>
</form>
</div>
@endsection
In routes/web.php
, use middleware to protect the dashboards:
// User routes
Route::middleware(['auth'])->group(function () {
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
});
// Admin routes
Route::middleware(['auth:admin'])->group(function () {
Route::get('/admin/dashboard', [App\Http\Controllers\AdminController::class, 'dashboard'])->name('admin.dashboard');
});
To test, you’ll need to create sample users and admins.
Use Laravel Tinker to add records:
php artisan tinker
Then run:
App\Models\User::create(['name' => 'User', 'email' => 'user@example.com', 'password' => bcrypt('password')]);
App\Models\Admin::create(['name' => 'Admin', 'email' => 'admin@example.com', 'password' => bcrypt('password')]);
Visit /login
, enter user@example.com
and password
, and you should be redirected to /home
.
Visit /admin/login
, enter admin@example.com
and password
, and you should be redirected to /admin/dashboard
.
Try accessing /admin/dashboard
without logging in as an admin; you should be redirected to /admin/login
. Similarly, accessing /home
without a user login should redirect to /login
.
You’ve successfully set up a Laravel 12 application with separate login systems for admins and users using distinct database tables and authentication guards. This approach keeps the authentication logic clean and scalable for applications requiring role-based access.
If you have questions or encounter issues, feel free to leave a comment. Happy coding with Laravel!
No comments yet. Be the first to comment!
Please log in to post a comment:
Continue with Google