Roles & Permissions — Manual Implementation
Roles and permissions control what users can do. You can implement them manually with a roles table and a role_user pivot, or use the popular spatie/laravel-permission package. This topic covers the manual approach to understand the fundamentals.
Manual Roles Implementation
// Migration for roles
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name')->unique(); // admin, editor, user
$table->timestamps();
});
Schema::create('role_user', function (Blueprint $table) {
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('role_id')->constrained()->cascadeOnDelete();
$table->primary(['user_id', 'role_id']);
});
// User model
public function roles(): BelongsToMany
{
return $this->belongsToMany(Role::class);
}
public function hasRole(string $role): bool
{
return $this->roles()->where('name', $role)->exists();
}
public function isAdmin(): bool
{
return $this->hasRole('admin');
}
// Middleware: app/Http/Middleware/CheckRole.php
public function handle(Request $request, Closure $next, string $role)
{
if (!$request->user()?->hasRole($role)) {
abort(403);
}
return $next($request);
}
// Route usage
Route::middleware('role:admin')->group(function () {
Route::resource('users', AdminUserController::class);
});Tip
Tip
Practice Roles Permissions Manual Implementation in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
Define the relationship, Eloquent builds the SQL automatically
Practice Task
Note
Practice Task — (1) Write a working example of Roles Permissions Manual Implementation from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with Roles Permissions Manual Implementation is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready laravel code.