Back to Course |
[Mini-Course] Laravel 11: Breeze with User Role Areas

Route Group: 3 Ways to Separate Groups by Roles

For student pages, let's introduce the route group.

We have only one timetable page for now, but what if you have more pages like messages, my profile, etc?

So what would you do: copy and paste more routes with the same prefix and route name? That would be a lot of repeating code.

Instead, we will create a route group and apply the same parameters to all of the URLs in that route group.


Route Group: Auth and Verified

First, we have a Route group, where we will use the same auth and verified for the Middleware.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware(['auth', 'verified'])
->group(function () {
Route::get('student/timetable', [\App\Http\Controllers\Student\TimetableController::class, 'index'])
->middleware(['auth', 'verified'])
->name('student.timetable');
});
 
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';

Next, we can add other groups. For example, we can group the student part of the URL by defining a prefix.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware(['auth', 'verified'])
->prefix('student')
->group(function () {
Route::get('student/timetable', [\App\Http\Controllers\Student\TimetableController::class, 'index'])
Route::get('timetable', [\App\Http\Controllers\Student\TimetableController::class, 'index'])
->middleware(['auth', 'verified'])
->name('student.timetable');
});
 
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';

We can also group by the name prefix student..

Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware(['auth', 'verified'])
->prefix('student')
->name('student.')
->group(function () {
Route::get('timetable', [\App\Http\Controllers\Student\TimetableController::class, 'index'])
->middleware(['auth', 'verified'])
->name('student.timetable');
->name('timetable');
});
 
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';

And, of course, we don't need the repeating Middleware.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware(['auth', 'verified'])
->prefix('student')
->name('student.')
->group(function () {
Route::get('timetable', [\App\Http\Controllers\Student\TimetableController::class, 'index'])
->middleware(['auth', 'verified'])
->name('timetable');
});
 
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';

Sub-Group In a Group

You can do a group within a group because some of the Middlewares repeat for all the routes, like auth and verified.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware(['auth', 'verified'])
Route::middleware(['auth', 'verified'])->group(function () {
->prefix('student')
Route::prefix('student')
->name('student.')
->group(function () {
Route::get('timetable', [\App\Http\Controllers\Student\TimetableController::class, 'index'])
->name('timetable');
});
});
 
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';

So, you would have a global route group for authenticated routes and, inside, group routes for students, teachers, admin, and others.

We can also move the dashboard route to the group.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
 
Route::prefix('student')
->name('student.')
->group(function () {
Route::get('timetable', [\App\Http\Controllers\Student\TimetableController::class, 'index'])
->name('timetable');
});
 
// Route groups for teachers/admins will be here
});
 
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';

Ok, so we've grouped the routes, reserving the place for the Routes for other roles in the (near) future.