Step 1: Install Spatie Laravel Permission
Start by installing the package via Composer and publishing its configurations:
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
Step 2: Rollback the Last Migration
If needed, you can rollback the last migration with this command:
php artisan migrate:rollback --step=1
Step 3: Re-run Migrations
If tables were deleted or require recreation, run:
php artisan migrate
Step 4: Update the User Model
Ensure the User model uses the HasRoles trait from Spatie:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// Other model methods...
}
Step 5: Create and Run a Seeder for Roles and Permissions
Create a seeder then populate roles and permissions:
php artisan make:seeder RolesAndPermissionsSeeder
php artisan db:seed --class=RolesAndPermissionsSeeder
Here’s what your seeder might look like:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class RolesAndPermissionsSeeder extends Seeder
{
public function run()
{
// Create roles
$roleSuperAdmin = Role::create(['name' => 'superadmin']);
$roleAdmin = Role::create(['name' => 'admin']);
$roleUser = Role::create(['name' => 'user']);
// More roles setup...
// Assign roles to users
$userOne = User::where('email', 'j@solarneutrino.com')->first();
if ($userOne) {
$userOne->assignRole('superadmin');
}
$userTwo = User::where('email', 'user@gmail.com')->first();
if ($userTwo) {
$userTwo->assignRole('user');
}
}
}
Follow these steps to effectively manage roles and permissions in your Laravel 11 application using the Spatie Permission package.
Step 6: Auto-Assign ‘User’ Role on Registration
To automatically assign the “user” role to all newly registered users, you need to modify the registration handling method. This is usually the create
method in the RegisterController
.
Open the
RegisterController.php
file, typically located in theapp/Http/Controllers/Auth
directory.Add the role assignment in the
create
method after creating a new user:protected function create(array $data) { $user = User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); // Assigning the "user" role $user->assignRole('user'); return $user; }
This code snippet ensures that every new user is automatically granted the “user” role upon registration.
Step 7: Using @role and @hasrole Directives in Blade Templates
To manage content visibility based on user roles within Blade templates, Laravel’s Spatie Permission package provides two useful directives: @role
and @hasrole
. These directives help in rendering content conditionally based on the user’s roles.
Examples:
<!-- Display content only if the user has the "superadmin" role. Checks for any of the specified roles if multiple are provided. -->
@role('superadmin')
<p>This text can see user from Superadmin group</p>
@endrole
<!-- Alternative way using @hasrole, strictly checks for the specified role. Used for checking a single role. -->
@hasrole('superadmin')
<p>This text can see user from Superadmin group</p>
@endhasrole
<!-- Display content only if the user has the "user" role. Checks for any of the specified roles if multiple are provided. -->
@role('user')
<p>This text can see user from User group</p>
@endrole
<!-- Alternative way using @hasrole, strictly checks for the specified role. Used for checking a single role. -->
@hasrole('user')
<p>This text can see user from User group</p>
@endhasrole
Explanations:
- @role: This directive checks if the current authenticated user has one or more specified roles. If multiple roles are passed (separated by commas), it returns true if the user has at least one of them. In the provided examples, only one role is specified, so the behavior is similar to @hasrole.
- @hasrole: This directive strictly checks if the user has the specified role. It’s ideal for situations where you need to verify the presence of only one specific role. This directive always takes only one role at a time.
These directives are instrumental in controlling what content a user can see based on their roles, enhancing security and user experience by tailoring the UI to meet individual user permissions.
Step 8: Applying Roles to Routes or Route Groups
In Laravel 11, the structure for handling middleware has changed significantly, including the deprecation of the app/Http/Kernel.php
file. Middleware can now be applied directly in the routing files such as web.php
or api.php
. Here’s how to set up and use Spatie Permission Middleware to restrict route access to users with specific roles.
Registering and Applying Middleware
You can register your middleware directly in the routing file. Below is a step-by-step guide on how to apply the Spatie Permission Middleware directly to your routes:
- Add the Middleware Namespace:
At the beginning of your routing file (e.g.,
routes/web.php
), add the namespace for the middleware:<?php use Spatie\Permission\Middlewares\RoleMiddleware; ?>
- Apply Middleware to a Route:
Apply the middleware directly to the routes as follows:
<?php use Illuminate\Support\Facades\Route; Route::middleware(['auth', 'verified', RoleMiddleware::class . ':superadmin']) ->get('/contact-messages', function () { return view('contact-messages'); })->name('contact-messages'); ?>
Note that we pass the
RoleMiddleware
class with the role parameter (superadmin
) directly into the middleware array.
Laravel 10, 9, …
To secure routes based on user roles, Laravel allows the application of middleware to individual routes or groups of routes. Using Spatie’s permission package, you can enforce role-based access controls effectively.
Applying Roles to a Single Route:
use Illuminate\Support\Facades\Route;
// Ensure you have registered the 'role' middleware in your old version Laravel - Kernel.php after Laravel 11 it can be seeder class or another tinker way.
Route::get('/admin', function () {
return view('admin.dashboard');
})->middleware('role:admin');
This route is accessible only to users who have the ‘admin’ role. If a user without this role tries to access it, they will be redirected as defined by your middleware handling.
Applying Roles to a Route Group:
use Illuminate\Support\Facades\Route;
Route::middleware(['role:admin'])->group(function () {
Route::get('/admin/dashboard', function() {
return view('admin.dashboard');
});
Route::get('/admin/settings', function() {
return view('admin.settings');
});
});
This group of routes is secured with the ‘admin’ role, ensuring that all routes within this group require a user to be an ‘admin’ to gain access. This method is particularly effective for sectioning parts of your application that should be restricted to users with specific roles.
Note: It’s important to ensure that your Kernel.php
file is properly configured to recognize the Spatie middleware. Add the Spatie middleware to your $routeMiddleware
array if it’s not already present:
protected $routeMiddleware = [
// other middleware
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
];
Following these best practices not only enhances the security of your application by ensuring proper role-based access control but also aligns with Spatie’s documentation, ensuring you are implementing features in the recommended manner.
For example:
Utilized Laravel Breeze for authentication with frontend-designed Tailwind CSS and Spatie for role-based access control. Integrated Laravel Sanctum for secure token-based API and Laravel Multidomain middleware for simpler project integration. Enhanced security by hosting the admin panel on a separate domain (admin.solarneutrino.com) and (solarneutrino.com). Implemented a contact form with functionalities for email notifications, logging via Eloquent MySQL, and Telegram alerts. Infrastructure set up on EC2, utilizing Route 53 for DNS management and AWS SES for email dispatch.