0
0
LaravelHow-ToBeginner · 4 min read

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 roles table and a pivot table like role_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 hasRole method 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

StepDescriptionExample
1Create roles and pivot tablesMigration for roles and role_user tables
2Define roles relationship in User modelpublic function roles() { return $this->belongsToMany(Role::class); }
3Add hasRole method to User modelpublic function hasRole($role) { return $this->roles()->where('name', $role)->exists(); }
4Create middleware to check rolesCheckRole middleware with handle method
5Register middleware in Kernel.php'role' => CheckRole::class
6Apply middleware to routesRoute::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.