We are entirely done with the student and the teacher areas, so let's recap and repeat the same thing for the third role of admin
.
First, let's seed the third third role.
app/database/seeders/DatabaseSeeder.php:
class DatabaseSeeder extends Seeder{ public function run(): void { Role::create(['name' => 'student']); Role::create(['name' => 'teacher']); Role::create(['name' => 'admin']); }}
Also, we don't allow admins to register, so let's create this user in the seeder. The most important parameter is to set role_id
when making an admin user.
app/database/seeders/DatabaseSeeder.php:
use App\Models\User; class DatabaseSeeder extends Seeder{ public function run(): void { Role::create(['name' => 'student']); Role::create(['name' => 'teacher']); Role::create(['name' => 'admin']); User::factory()->create([ 'name' => 'Admin', 'email' => 'admin@admin.com', 'role_id' => 3, ]); }}
We can re-migrate and seed the admin user.
php artisan migrate:fresh --seed
At this point, we can already log in as an admin, but we don't have an admin area. So, let's do a lot of save as to new files for the admin layout and other files. By doing that, you will kind of repeat all the things that we've done in the previous lessons.
First, let's create a Controller.
php artisan make:controller Admin/UserController
app/Http/Controllers/Admin/UserController.php:
use Illuminate\Contracts\View\View;use App\Http\Controllers\Controller; class UserController extends Controller{ public function index(): View { return view('admin.users'); }}
Next, add this Controller to the Routes by creating a new Route group.
routes/web.php:
use Illuminate\Support\Facades\Route;use App\Http\Controllers\ProfileController;use App\Http\Controllers\Student;use App\Http\Controllers\Teacher;use App\Http\Controllers\Admin; Route::get('/', function () { return view('welcome');}); Route::middleware(['auth', 'verified'])->group(function () { Route::prefix('student') ->middleware('role:1') ->name('student.') ->group(function () { Route::get('timetable', [Student\TimetableController::class, 'index']) ->name('timetable'); }); Route::prefix('teacher') ->middleware('role:2') ->name('teacher.') ->group(function () { Route::get('timetable', [Teacher\TimetableController::class, 'index']) ->name('timetable'); }); Route::prefix('admin') ->middleware('role:3') ->name('admin.') ->group(function () { Route::get('user', [Admin\UserController::class, 'index']) ->name('users'); }); }); Route::middleware('auth')->group(function () { Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit'); Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update'); Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');}); require __DIR__ . '/auth.php';
Now, let's create a View file. The content of the View file will be identical to any of the timetable View files, only with different text.
resources/views/admin/users.blade.php:
<x-admin-layout> <x-slot name="header"> <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight"> {{ __('Users List') }} </h2> </x-slot> <div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg"> <div class="p-6 text-gray-900 dark:text-gray-100"> {{ __('List coming soon.') }} </div> </div> </div> </div></x-admin-layout>
In this View, we used a new layout Blade component, admin-layout
. We must create it now.
Using your editor, save as one of the layouts class files or copy its content to a new AdminLayout
PHP class, change the class name, and return the View file name.
app/View/Components/AdminLayout.php:
use Illuminate\View\View;use Illuminate\View\Component; class AdminLayout extends Component{ public function render(): View { return view('layouts.admin'); }}
Repeat the process from the other View layout files. Change only the navigation path. Then, change the background color.
resources/views/layouts/admin.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"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Laravel') }}</title> <!-- Fonts --> <link rel="preconnect" href="https://fonts.bunny.net"> <link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" /> <!-- Scripts --> @vite(['resources/css/app.css', 'resources/js/app.js']) </head> <body class="font-sans antialiased"> <div class="min-h-screen bg-red-50 dark:bg-gray-900"> @include('layouts.navigation.admin') <!-- Page Heading --> @isset($header) <header class="bg-white dark:bg-gray-800 shadow"> <div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8"> {{ $header }} </div> </header> @endisset <!-- Page Content --> <main> {{ $slot }} </main> </div> </body></html>
Remember to re-compile classes:
npm run dev
ornpm run build
.
Then, repeat the same process to create the admin navigation from any other navigation. The admin layout will have navigation items for the user list page.
resources/views/layouts/navigation/admin.blade.php:
<nav x-data="{ open: false }" class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">// ... <div class="flex"> <!-- Logo --> <div class="shrink-0 flex items-center"> <a href="{{ route('admin.users') }}"> <x-application-logo class="block h-9 w-auto fill-current text-gray-800 dark:text-gray-200" /> </a> </div> <!-- Navigation Links --> <div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex"> <x-nav-link :href="route('admin.users')" :active="request()->routeIs('admin.users')"> {{ __('Users') }} </x-nav-link> </div> </div>// ...</nav>
Also, we must add the redirect for the admin role.
app/Models/User.php:
class User extends Authenticatable{ // ... public function getRedirectRouteName(): string { return match ((int) $this->role_id) { 1 => 'student.timetable', 2 => 'teacher.timetable', 3 => 'admin.users', }; }}
After logging in with the admin user, we should be redirected to the correct page. Other pages will not be accessible.
That's it. We've completed the fundamental architecture for three different roles with three layouts and three route groups.
Their controllers are separated by namespaces, and views are also separated in their folders. You can work on each of them separately. Come up with different designs or logic only for teachers, students, or admins.
I hope this quick walk-through was helpful.
Repository is available on GitHub here.