When creating an application, you will need some restrictions for your users. Laravel offers a variety of ways how to implement this. In this tutorial, I will show you four examples:
- Simple Middleware
- Restriction with Gates
- From Gates to Policies
- Roles in DB with Model
There are also well-known packages like spatie/laravel-permission, but for the purpose of this article, I deliberately want to show what Laravel offers in its core, without external packages.
Scenario Setup
In this example, we will work with Users and Tasks and allow different users to access different pages related to the tasks.
Here's our setup:
Migrations
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->boolean('is_admin')->default(0); $table->rememberToken(); $table->timestamps();}); Schema::create('tasks', function (Blueprint $table) { $table->id(); $table->foreignId('user_id')->constrained(); $table->string('name'); $table->date('due_date'); $table->timestamps();});
Now, let's define the relationships:
app/Models/User.php
use App\Models\Task; // ... public function tasks(){ return $this->hasMany(Task::class);}
app/Models/Task.php
use App\Models\User; // ... public function user(){ return $this->belongsTo(User::class);}
Example 1. Middleware: Different Pages by User Role
In this example, we'll separate our routes/models and controllers by user role. It means that we will have two pages - one for the simple user and one for the admin, and we will restrict it with Middleware.
So, we generate this Middleware class:
php artisan make:middleware IsAdmin
app/Http/Middleware/IsAdmin.php
public function handle(Request $request, Closure $next): Response{ if (!auth()->check() || !auth()->user()->is_admin) { abort(403); } return $next($request);}
As you can see, we just have the field users.is_admin in the DB and filter by that.
Next, we need to...
Premium Members Only
This advanced tutorial is available exclusively to Laravel Daily Premium members.
Already a member? Login here
Premium membership includes:
Comments & Discussion
What if you have to check the database through the policy and you have like 20 buttons with the same gate around it?
I've been using a session with the permissions in there on login so i can just check the session instead of queries. But maybe there is a better way im not aware of?
Hello, first thanks for this tutorial.
I came up with a situation where I am not sure how to use the policies. I have a route to test email notification, but I want to open it only to super_admin (I am using filament shield which user Spatie permission). I have created an EmailPolicy with the method test() in it and the appropriate return. My question is how do I set up the policy registration inside the Service Provider as it is not linked to any model I have in my domain (there is no Model Email) ? Should I just use a get definition ? How would you handle it ? Thanks a lot.
Would you consider using roles table or a field role enum('admin','user','manager') in your app for roles if it's just roles?
Personally, I have enum fields in the DB cause they are hard to change in the future, I prefer separate DB tables whenever possible. But it's my personal preference.