Laravel Roles & Permissions 2026 — Full Beginner Tutorial

Author

Kritim Yantra

Dec 20, 2025

Laravel Roles & Permissions 2026 — Full Beginner Tutorial

If you’ve ever built a Laravel project and thought:

“Okay… users can log in, but now what?”
“How do I stop normal users from accessing admin features?”
“Why does everyone online explain this differently?”

Trust me—you’re not alone.

Most beginners hit this wall right after authentication. Login and registration feel great… until you realize real apps need rules.

  • Who can delete users?
  • Who can edit posts?
  • Who can access admin pages?
  • Why does one wrong middleware break everything? 😅

In this Laravel 2026 tutorial, we’ll walk through roles and permissions like a human would explain it to a friend—step by step, no magic, no confusion.

By the end, you’ll know:

  • ✅ What roles and permissions really are
  • All common ways to implement them in Laravel
  • ✅ Which approach is best for beginners vs large apps
  • ✅ Clean architecture + best practices for 2026

First, let’s understand the idea (no code yet)

Think of your app like an office building :

  • Roles = Job titles
    (Admin, Editor, User, Manager)

  • Permissions = Keys
    (Create post, Edit post, Delete user, View reports)

A role is just a collection of permissions.

👉 Instead of saying “John can edit posts, delete posts, approve posts…”
You say: “John is an Editor.”

Much cleaner. Much safer.


Roles vs Permissions (quick clarity)

Concept Meaning Example
Role Group of abilities Admin, User, Editor
Permission Single ability create-post, delete-user
User Has role(s) John = Admin
System Checks permission Can John delete users?

Pro Tip 
Roles answer “who you are”
Permissions answer “what you can do”


How many ways can we set up roles & permissions in Laravel?

This is where beginners get overwhelmed, so let’s simplify.

There are 4 common approaches

1️⃣ Hardcoded role checks (simple, not scalable)
2️⃣ Role column in users table
3️⃣ Custom roles & permissions tables
4️⃣ Spatie Laravel Permission package (industry standard)

We’ll cover all four, then I’ll tell you which one to use and why.


Method 1: Hardcoded role checks (NOT recommended long-term)

Example:

@if(auth()->user()->is_admin)
   // show admin button
@endif

Or:

if(auth()->user()->role === 'admin') {
   // allow
}

Why beginners start here

  • Easy to understand
  • Fast to implement
  • No extra tables

Why it becomes painful 

  • Logic scattered everywhere
  • Hard to change later
  • Not flexible at all

Warning ️
This approach works for tiny apps only. Once you have more than 2 roles, it becomes technical debt.


Method 2: Role column in users table (okay for small apps)

Step 1: Add role column

php artisan make:migration add_role_to_users_table
Schema::table('users', function (Blueprint $table) {
    $table->string('role')->default('user');
});

Now your users table has:

id | name | email | role

Step 2: Check role

if(auth()->user()->role === 'admin') {
    // admin access
}

Middleware example

php artisan make:middleware IsAdmin
public function handle($request, Closure $next)
{
    if (auth()->user()->role !== 'admin') {
        abort(403);
    }
    return $next($request);
}

When this is okay

  • Personal projects
  • Simple dashboards
  • 2–3 roles max

Limitation

  • No real permissions
  • Every role logic is manual

Method 3: Custom Roles & Permissions Tables (manual but powerful)

This is where things start feeling professional.

Database structure (classic RBAC)

Tables:

  • users
  • roles
  • permissions
  • role_user (pivot)
  • permission_role (pivot)

Example tables

roles

id | name

permissions

id | name

role_user

user_id | role_id

permission_role

permission_id | role_id

Eloquent relationships

// User.php
public function roles() {
    return $this->belongsToMany(Role::class);
}
// Role.php
public function permissions() {
    return $this->belongsToMany(Permission::class);
}

Permission check

auth()->user()
     ->roles
     ->pluck('permissions')
     ->flatten()
     ->contains('name', 'edit-post');

Reality check

This works—but:

  • A LOT of boilerplate
  • Easy to mess up
  • Time-consuming to maintain

Pro Tip 
If you’re learning deeply, this is great.
If you’re building a real app? There’s a better way.


Method 4 (BEST): Spatie Laravel Permission (Recommended for 2026)

This is the industry standard.

Used in:

  • SaaS apps
  • Admin panels
  • Large Laravel projects

Why developers love it

  • Clean API

  • Battle-tested

  • Supports:

    • Multiple roles
    • Direct permissions
    • Middleware
    • Caching (fast!)

Installing Spatie Laravel Permission

composer require spatie/laravel-permission

Publish config & migrations:

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate

This creates:

  • roles
  • permissions
  • model_has_roles
  • model_has_permissions
  • role_has_permissions

Prepare User model

In User.php:

use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}

That’s it. No magic—just traits.


Create roles & permissions

Seeder example

use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

Permission::create(['name' => 'create-post']);
Permission::create(['name' => 'edit-post']);
Permission::create(['name' => 'delete-post']);

$admin = Role::create(['name' => 'admin']);
$editor = Role::create(['name' => 'editor']);

$admin->givePermissionTo(Permission::all());
$editor->givePermissionTo(['create-post', 'edit-post']);

Assign role to user

$user->assignRole('admin');

Or multiple roles:

$user->assignRole(['admin', 'editor']);

Check permissions (super clean)

if(auth()->user()->can('delete-post')) {
    // allowed
}

Blade:

@can('edit-post')
   <button>Edit</button>
@endcan

Middleware:

Route::get('/admin', function () {
    //
})->middleware('permission:access-admin');

Or role-based:

->middleware('role:admin')

This is why Spatie wins.
Readable. Maintainable. Scalable.


Best Practices for Laravel Roles & Permissions (2026)

1. Always use permissions for actions

Roles are just containers.
Permissions control real power.

2. Don’t hardcode roles in views

Use:

@can('delete-user')

Not:

@if(auth()->user()->role === 'admin')

3. Cache permissions (Spatie does this automatically)

Faster app, fewer DB queries.

4. Keep permission names readable

Good:

edit-post
delete-user
view-dashboard

Bad:

p1
canEditSomething

5. Seed roles & permissions

Never create them manually in production.


Which approach should YOU choose?

Project Type Recommendation
Learning basics Role column
Small app Role column + middleware
Medium app Spatie Permission
Large / SaaS Spatie Permission (100%)

If you remember one thing from this blog:
👉 Use Spatie for real projects.


FAQ (Beginner-friendly)

1) Can a user have multiple roles?

Yes! Especially with Spatie. One user can be both editor and manager.

2) Should I use roles OR permissions?

Use both—but check permissions, not roles.

3) Is Spatie secure?

Yes. It’s widely used, actively maintained, and production-ready.


Final thoughts (personal advice)

I’ve built Laravel apps where roles were an afterthought—and fixing them later was painful.

If you’re starting a project today:

  • Spend 30 extra minutes
  • Set roles & permissions properly
  • Your future self will thank you 

Now I want to hear from you 👇

What confuses you the most about Laravel roles and permissions—database design, middleware, or deciding which approach to use? Share your struggle, and I’ll help you untangle it.

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts