Laravel 12 Table Relationships: A Complete Guide to Roles and Permissions (RBAC)

Author

Kritim Yantra

May 25, 2025

Laravel 12 Table Relationships: A Complete Guide to Roles and Permissions (RBAC)

Building modern web applications often requires controlling user access to specific features. Whether it's an admin-only dashboard or content restricted by roles, Role-Based Access Control (RBAC) is the go-to solution. In this comprehensive guide, we’ll walk you through setting up Roles and Permissions in Laravel 12, covering:

✅ Database design
✅ Model relationships
✅ Middleware for access control
✅ Blade directives for views
✅ Seeding roles and permissions

Let's get started!


🚀 What is RBAC?

Role-Based Access Control (RBAC) is a system where you assign permissions to roles, and then roles to users. For example:

  • The Admin role might have permissions to manage users, edit content, and publish articles.
  • A User role may only view content.

This setup ensures a clean, maintainable system for controlling access across your Laravel application.


🏗️ Database Design

We'll need the following tables:

📂 1. users table (default in Laravel)

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

📂 2. roles table

Schema::create('roles', function (Blueprint $table) {
    $table->id();
    $table->string('name')->unique();
    $table->string('description')->nullable();
    $table->timestamps();
});

📂 3. permissions table

Schema::create('permissions', function (Blueprint $table) {
    $table->id();
    $table->string('name')->unique();
    $table->string('description')->nullable();
    $table->timestamps();
});

📂 4. Pivot Tables

role_user (many-to-many: users ↔️ roles)

Schema::create('role_user', function (Blueprint $table) {
    $table->foreignId('role_id')->constrained()->cascadeOnDelete();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->primary(['role_id', 'user_id']);
});

permission_role (many-to-many: roles ↔️ permissions)

Schema::create('permission_role', function (Blueprint $table) {
    $table->foreignId('permission_id')->constrained()->cascadeOnDelete();
    $table->foreignId('role_id')->constrained()->cascadeOnDelete();
    $table->primary(['permission_id', 'role_id']);
});

🧩 Defining Model Relationships

👤 User Model

public function roles()
{
    return $this->belongsToMany(Role::class);
}

public function assignRole($role)
{
    if (is_string($role)) {
        $role = Role::whereName($role)->firstOrFail();
    }
    return $this->roles()->syncWithoutDetaching($role);
}

public function hasRole($role)
{
    if (is_string($role)) {
        return $this->roles->contains('name', $role);
    }
    return !! $role->intersect($this->roles)->count();
}

public function permissions()
{
    return $this->roles->map->permissions->flatten()->pluck('name')->unique();
}

public function hasPermission($permission)
{
    return $this->permissions()->contains($permission);
}

🎓 Role Model

public function users()
{
    return $this->belongsToMany(User::class);
}

public function permissions()
{
    return $this->belongsToMany(Permission::class);
}

public function givePermissionTo($permission)
{
    if (is_string($permission)) {
        $permission = Permission::whereName($permission)->firstOrFail();
    }
    return $this->permissions()->syncWithoutDetaching($permission);
}

🔒 Permission Model

public function roles()
{
    return $this->belongsToMany(Role::class);
}

🔑 Assigning Roles and Permissions

✅ Assign a Role to a User

$user = User::find(1);
$user->assignRole('admin');

✅ Give Permission to a Role

$adminRole = Role::where('name', 'admin')->first();
$adminRole->givePermissionTo('edit-users');

✅ Check Roles and Permissions

if ($user->hasRole('admin')) {
    // Admin access granted
}

if ($user->hasPermission('edit-users')) {
    // Permission granted
}

🛡️ Middleware for Route Protection

Role Middleware

Create:

php artisan make:middleware RoleMiddleware

Implement:

public function handle(Request $request, Closure $next, $role)
{
    if (!auth()->user()->hasRole($role)) {
        abort(403, 'Unauthorized action.');
    }
    return $next($request);
}

Register in Kernel.php:

'role' => \App\Http\Middleware\RoleMiddleware::class,

Usage:

Route::get('/admin', fn() => 'Admin Panel')->middleware(['auth', 'role:admin']);

Permission Middleware

Similar steps apply:

php artisan make:middleware PermissionMiddleware

Implement:

public function handle(Request $request, Closure $next, $permission)
{
    if (!auth()->user()->hasPermission($permission)) {
        abort(403, 'Unauthorized action.');
    }
    return $next($request);
}

🖌️ Blade Directives

Add to AppServiceProvider:

Blade::if('role', fn($role) => auth()->check() && auth()->user()->hasRole($role));
Blade::if('permission', fn($permission) => auth()->check() && auth()->user()->hasPermission($permission));

Usage:

@role('admin')
    <p>Welcome, Admin!</p>
@endrole

@permission('edit-users')
    <button>Edit User</button>
@endpermission

🌱 Seeding Initial Roles & Permissions

Create a seeder:

php artisan make:seeder RolesAndPermissionsSeeder

Example:

public function run()
{
    $admin = Role::create(['name' => 'admin']);
    $editor = Role::create(['name' => 'editor']);

    $permissions = ['manage-users', 'edit-content', 'publish-content'];
    foreach ($permissions as $perm) {
        Permission::create(['name' => $perm]);
    }

    $admin->givePermissionTo(Permission::all());
    $editor->givePermissionTo(['edit-content', 'publish-content']);
}

Run:

php artisan db:seed --class=RolesAndPermissionsSeeder

✨ Best Practices

✅ Use Enums for role/permission names.
Cache permissions for performance.
✅ Build an admin UI for roles & permissions.
✅ Add audit logs for changes.
✅ Write tests for authorization logic.


🏁 Conclusion

By following this guide, you now have a powerful, flexible, and scalable Roles & Permissions system in Laravel 12! 🚀

✅ Database relationships? ✔️
✅ Model methods? ✔️
✅ Middleware & Blade directives? ✔️
✅ Seeding data? ✔️

Keep building and securing your Laravel apps with confidence! 💪

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts