Courses

Roles and Permissions in Laravel 12

Roles in Separate DB Table

You're reading a FREE PREVIEW of a PREMIUM course.
Summary of this lesson:
- Moving from is_admin to dedicated roles table
- Creating role constants to avoid magic numbers
- Implementing role-based Policy checks
- Converting role checks to use foreign keys
- Testing different role permissions scenarios

Video Version of the Lesson

[Only for premium members]

Link to the repository

[Only for premium members]

In the first lessons, we relied on the users.is_admin column to define permissions. But what if there are more than two roles? Then you probably need to create a separate DB table, roles, and add a users.role_id column with a foreign key. This is precisely what we will cover in this lesson.

Imagine we have three roles:

  • Simple user: can only view the list of tasks
  • Administrator: can do everything with tasks - view/create/update/delete
  • Manager: can only view and update tasks created by the administrator

As usual, by the end of the lesson we will have a repository with automated tests, including the ones from default Laravel Breeze:


The Key Point: Policy

We will continue on the example of the last lesson, where the main logic is inside of TaskPolicy. By the end of this lesson, we will change the conditions here. Our starting point is this:

app/Policies/TaskPolicy.php

class TaskPolicy
{
public function create(User $user): bool
{
return true;
}
 
public function update(User $user, Task $task): bool
{
return $user->is_admin || $task->user_id === $user->id;
}
 
public function delete(User $user, Task $task): bool
{
return $user->is_admin || $task->user_id === $user->id;
}
}

Let's change that $user->is_admin to something more flexible.


Migrations and Models for Separate Roles Table

Migration

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

app/Models/Role.php

class Role extends Model
{
use HasFactory;
 
protected $fillable = ['name'];
}

database/seeders/RoleSeeder.php

use App\Models\Role;
 
// ...
 
class RoleSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Role::create(['name' => 'User']);
Role::create(['name' => 'Administrator']);
Role::create(['name' => 'Manager']);
}
}

And, of course, call the seeder:

database/seeders/DatabaseSeeder.php

class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
$this->call(RoleSeeder::class);
}
}

Then, we add a foreign key with...

The full lesson is only for Premium Members.
Want to access all 13 video+text lessons of this course? (57 min)

You also get:

  • 77 courses
  • Premium tutorials
  • Access to repositories
  • Private Discord