How to Implement Role Based Access in Laravel Easily
In Laravel, implement role based access by defining user roles in your database and using
middleware to restrict routes based on roles. You can also use policies to control access to specific actions within controllers.Syntax
Role based access in Laravel typically involves these parts:
- Roles stored in database: Assign roles to users via a
rolestable and a pivot table likerole_user. - Middleware: Create middleware to check user roles before allowing access to routes.
- Policies: Define authorization logic for specific models or actions.
php
<?php // Middleware example to check role namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class CheckRole { public function handle(Request $request, Closure $next, $role) { if (! $request->user() || ! $request->user()->hasRole($role)) { abort(403, 'Unauthorized'); } return $next($request); } } // User model method example public function hasRole($role) { return $this->roles()->where('name', $role)->exists(); }
Example
This example shows how to create a middleware to restrict access to admin routes and how to assign roles to users.
php
<?php // 1. Migration for roles table use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateRolesTable extends Migration { public function up() { Schema::create('roles', function (Blueprint $table) { $table->id(); $table->string('name')->unique(); $table->timestamps(); }); Schema::create('role_user', function (Blueprint $table) { $table->foreignId('user_id')->constrained()->onDelete('cascade'); $table->foreignId('role_id')->constrained()->onDelete('cascade'); $table->primary(['user_id', 'role_id']); }); } public function down() { Schema::dropIfExists('role_user'); Schema::dropIfExists('roles'); } } // 2. User model relationship and method namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { public function roles() { return $this->belongsToMany(Role::class); } public function hasRole($role) { return $this->roles()->where('name', $role)->exists(); } } // 3. Middleware to check role namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class CheckRole { public function handle(Request $request, Closure $next, $role) { if (! $request->user() || ! $request->user()->hasRole($role)) { abort(403, 'Unauthorized'); } return $next($request); } } // 4. Register middleware in Kernel.php // 'role' => \App\Http\Middleware\CheckRole::class, // 5. Use middleware in routes/web.php use Illuminate\Support\Facades\Route; Route::middleware(['auth', 'role:admin'])->group(function () { Route::get('/admin', function () { return 'Welcome Admin'; }); });
Output
When a logged-in user with role 'admin' visits /admin, they see: Welcome Admin
If not admin, they get a 403 Unauthorized error.
Common Pitfalls
Common mistakes when implementing role based access in Laravel include:
- Not defining the
hasRolemethod in the User model, causing role checks to fail. - Forgetting to register the middleware in
app/Http/Kernel.php, so it never runs. - Not attaching roles to users in the database, so all role checks return false.
- Using string role names inconsistently (e.g., 'Admin' vs 'admin'), causing mismatches.
- Not protecting routes properly by missing middleware or using incorrect middleware parameters.
php
<?php // Wrong: Missing hasRole method // User model lacks role check, so middleware always aborts // Right: Add hasRole method public function hasRole($role) { return $this->roles()->where('name', strtolower($role))->exists(); }
Quick Reference
| Step | Description | Example |
|---|---|---|
| 1 | Create roles and pivot tables | Migration for roles and role_user tables |
| 2 | Define roles relationship in User model | public function roles() { return $this->belongsToMany(Role::class); } |
| 3 | Add hasRole method to User model | public function hasRole($role) { return $this->roles()->where('name', $role)->exists(); } |
| 4 | Create middleware to check roles | CheckRole middleware with handle method |
| 5 | Register middleware in Kernel.php | 'role' => CheckRole::class |
| 6 | Apply middleware to routes | Route::middleware(['auth', 'role:admin'])->group(...) |
Key Takeaways
Define roles in your database and link them to users with a many-to-many relationship.
Create middleware to check user roles and protect routes accordingly.
Always register your middleware in Kernel.php to activate it.
Use consistent role naming and implement a hasRole method in the User model.
Test role access by assigning roles to users and visiting protected routes.