Black Friday: coupon FRIDAY24 for 40% off Yearly/Lifetime membership! Read more here
Courses

Roles and Permissions in Laravel 11

One of the most typical questions I received when preparing for this course was, "Will you use the Spatie Permissions package?"

And I thought, "Why not BOTH". So, first, I've shown you how to use gates/policies without any packages, and now it's time to show the "other side".


Starting Point

We will work on the same project but take its "earlier" point. Imagine we have Gates without Policies.

app/Http/Controllers/TaskController.php

class TaskController extends Controller
{
public function index(): View
{
$tasks = Task::with('user')->get();
 
return view('tasks.index', compact('tasks'));
}
 
public function create(): View
{
Gate::authorize('create', Task::class);
 
return view('tasks.create');
}
 
public function store(Request $request): RedirectResponse
{
Gate::authorize('create', Task::class);
 
Task::create($request->only('name', 'due_date')
+ ['user_id' => auth()->id()]);
 
return redirect()->route('tasks.index');
}
 
public function edit(Task $task): View
{
Gate::authorize('update', $task);
 
return view('tasks.edit', compact('task'));
}
 
public function update(Request $request, Task $task): RedirectResponse
{
Gate::authorize('update', $task);
 
$task->update($request->only('name', 'due_date'));
 
return redirect()->route('tasks.index');
}
 
public function destroy(Task $task): RedirectResponse
{
Gate::authorize('delete', $task);
 
$task->delete();
 
return redirect()->route('tasks.index');
}
}

And then we have @can checks in the Blade file.

resources/views/tasks/index.blade.php

<div class="min-w-full align-middle">
@can('create', \App\Models\Task::class)
<a href="{{ route('tasks.create') }}" class="underline">Add new task</a>
<br /><br />
@endcan
<table class="min-w-full border divide-y divide-gray-200">
<thead>
...
</thead>
 
<tbody class="bg-white divide-y divide-gray-200 divide-solid">
@foreach($tasks as $task)
<tr class="bg-white">
 
...
 
<td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap">
@can('update', $task)
<a href="{{ route('tasks.edit', $task) }}" class="underline">Edit</a>
@endcan
@can('delete', $task)
|
<form action="{{ route('tasks.destroy', $task) }}"
method="POST"
class="inline-block"
onsubmit="return confirm('Are you sure?')">
@method('DELETE')
@csrf
<button type="submit" class="text-red-600 underline">Delete</button>
</form>
@endcan
</td>
</tr>
@endforeach
</tbody>
</table>
</div>

Now, let's install the package and configure its roles.


Installing Spatie Permissions Package

We'll do everything according to basic official documentation.

composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

Then, we need to add a trait to our User Model and remove our own roles implementation:

app/Models/User.php

use Spatie\Permission\Traits\HasRoles;
 
// ...
 
class User extends Authenticatable
{
use HasFactory, Notifiable;
use HasRoles;
 
// ...
 
protected $fillable = [
'name',
'email',
'password',
'role_id',
];
 
// ...
 
public function role(): BelongsTo
{
return $this->belongsTo(Role::class);
}
}

We also removed the role_id and the relationship we had in the beginning. It will all be saved in the...

This lesson is only for Premium Members.
Want to access all lessons of this course?

You also get:

  • 67 courses (1172 lessons, 43 h 18 min total)
  • Premium tutorials
  • Access to repositories
  • Private Discord