Laravel 12 User Roles and Permissions with a Spatie package
Role-based access control (RBAC) is essential for most web applications. In this tutorial, I’ll show you how to implement a robust…
Laravel 12 User Roles and Permissions with a Spatie package
Role-based access control (RBAC) is essential for most web applications. In this tutorial, I’ll show you how to implement a robust permission system in Laravel 12 using the popular Spatie Laravel-Permission package.

Spatie Role Permission
Why Spatie Permissions?
The Spatie Laravel-Permission package provides:
- Simple role and permission management
- Middleware protection for routes
- Blade directives for view protection
- Database caching for optimal performance
- Clean, maintainable code structure
Step 1: Install Spatie Laravel-Permission your project
To install the Spatie Laravel Permission (ACL) package, you’ll need to run the following commands in your terminal inside your Laravel project:
composer require spatie/laravel-permission
Once you install the Spatie Laravel Permission package with the version you need, you can publish its config and migration files so you can customize them. Run the following command in your terminal:
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
After publishing, you’ll see the config/permission.php file and the migration file inside database/migrations/.
Now, to create the necessary tables for roles and permissions, just run:
php artisan migrate
Step 2: Set Up the User Model
To enable role & permission management on your User model, you need to add the HasRoles trait from Spatie.
Open your app/Models/User.php file and update it like this:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// ... rest of your model code
}
You just need to alias them in bootstrap/app.php (since Laravel 11+ doesn’t use the old Kernel.php for middleware registration).
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
3. Create Roles & Permissions (Seeder Example)
<?php
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class RolePermissionSeeder extends Seeder
{
public function run(): void
{
Permission::create(['name' => 'view articles']);
Permission::create(['name' => 'create articles']);
Permission::create(['name' => 'edit articles']);
Permission::create(['name' => 'delete articles']);
// Create roles and assign permissions
$writer = Role::create(['name' => 'writer']);
$writer->givePermissionTo(['view articles', 'create articles', 'edit articles']);
$admin = Role::create(['name' => 'admin']);
$admin->givePermissionTo(Permission::all());
}
}
Run seeder:
php artisan db:seed --class=RolePermissionSeeder
4. Assign Roles to Users
$user = User::find(1);
$user->assignRole('admin');
$writer = User::find(2);
$writer->assignRole('writer');
5. Protect Routes with Middleware
Route::middleware(['role:admin'])->group(function () {
Route::get('/admin/dashboard', fn() => 'Admin Dashboard');
});
Route::get('/articles/create', fn() => 'Create Article Page')
->middleware('permission:create articles');
6. Blade Protection With can function
Because all permissions will be registered on Laravel’s gate, you can check if a user has a permission with Laravel’s default can function:
@can('edit articles')
<button>Edit</button>
@endcan
7. FormRequest Authorization (Best Practice)
Instead of checking permissions in controllers, use FormRequest classes.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateArticleRequest extends FormRequest
{
public function authorize(): bool
{
// Only allow if user has "create articles" permission
return $this->user()?->can('create articles');
}
public function rules(): array
{
return [
'title' => 'required|string|max:255',
'content' => 'required|string',
];
}
}
Example: UpdateArticleRequest
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateArticleRequest extends FormRequest
{
public function authorize(): bool
{
// Allow only if user can "edit articles"
return $this->user()?->can('edit articles');
}
public function rules(): array
{
return [
'title' => 'sometimes|required|string|max:255',
'content' => 'sometimes|required|string',
];
}
}
Using in Controller
<?php
namespace App\Http\Controllers;
use App\Models\Article;
use App\Http\Requests\CreateArticleRequest;
use App\Http\Requests\UpdateArticleRequest;
class ArticleController extends Controller
{
public function store(CreateArticleRequest $request)
{
Article::create($request->validated());
return back()->with('success', 'Article created!');
}
public function update(UpdateArticleRequest $request, Article $article)
{
$article->update($request->validated());
return back()->with('success', 'Article updated!');
}
}
If the user does not have the required permission, Laravel automatically throws 403 Unauthorized before entering the controller.
Conclusion
Spatie’s Laravel Permission package gives you a clean and flexible way to handle role-based access control (RBAC) in your application. By combining middleware, Blade directives, and FormRequest authorization, you can protect your routes, controllers, and views with minimal effort.
- Middleware ensures routes are secure.
- Blade directives ensure the UI only shows what’s allowed.
- FormRequests keep controllers clean while enforcing permissions automatically.
With this setup, your app follows best practices in authorization and stays scalable as your roles and permissions grow. Whether you’re building a small blog or a large enterprise system, this approach ensures your application remains secure, maintainable, and easy to extend.
If you found this helpful, feel free to share or drop a comment. Happy coding with Laravel! 🧱✨
메타데이터
- post_id
- 12510d0f97aa
- slug
- laravel-12-user-roles-and-permissions-with-a-spatie-package-12510d0f97aa
- url
- https://medium.com/@devtalk94/laravel-12-user-roles-and-permissions-with-a-spatie-package-12510d0f97aa
- canonical_url
- https://medium.com/@devtalk94/laravel-12-user-roles-and-permissions-with-a-spatie-package-12510d0f97aa
- author_url
- https://medium.com/@devtalk94
- status
- ok
- fetched_at
- 2026-07-18 04:29:11