How to make multiple roles in Spatie Laravel package?
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
How to Make Multiple Roles in Spatie Laravel Package: Linking Permissions to Resources
The desire to implement complex permission structures, like those seen on platforms such as Facebook—where roles are dynamically assigned based on ownership of specific resources (like Pages)—is a common requirement in modern application development. You are absolutely right; the standard setup using the Spatie laravel-permission package handles user permissions excellently, but it doesn't inherently manage the many-to-many relationship between users, roles, and specific models (like Pages).
This post will dive into how to extend the functionality of Spatie to achieve this resource-based permission management, allowing you to ask not just "Does the user have the 'admin' role?" but "Is the user an admin of this specific page?".
The Limitation of Basic Role Assignment
As you correctly identified, the standard commands like $user->hasRole('admin') only check the permissions assigned directly to that user. If we simply assign a role to a User model, checking for that role is global. To solve your problem—linking roles to specific Pages—we need an additional layer of relationship management in our database and Eloquent code.
We cannot rely solely on the built-in Spatie structure; we must build the necessary bridge between the permission system and your resource models (Pages). This architectural approach mirrors how robust systems, including those fostered by Laravel principles, manage complex data relationships, emphasizing clean separation of concerns, which is a core philosophy at https://laravelcompany.com.
The Solution: Implementing Resource-Specific Roles
To achieve what you are describing, the most effective method involves creating pivot tables that explicitly define the relationship between a Role and a Model (in this case, a Page). This shifts the focus from "What roles does the user have?" to "What permissions does this user have on this resource?".
Step 1: Database Structure Setup
You need three main components for this setup: Users, Pages, and a pivot table linking Roles to Pages.
- Users & Roles: These remain as you set them up with Spatie (User $\leftrightarrow$ Role).
- Pages: Your resource model.
- Pivot Table (The Link): This is the crucial part. You need a pivot table that defines which roles apply to which pages.
A simplified conceptual database structure might involve:
roles(id, name)pages(id, name)role_user(many-to-many between users and roles, standard Spatie setup)page_roles(Pivot table):page_id,role_id. This explicitly states that Role X is assigned to Page Y.
Step 2: Eloquent Relationships
Once the database is structured, you must define these relationships in your Eloquent models. For example, on the Page model, you would define a relationship to the roles it governs:
// app/Models/Page.php
public function pageRoles()
{
return $this->belongsToMany(Role::class);
}
Step 3: Implementing Resource-Based Checks
Now, instead of checking permissions on the User model alone, you check the relationship on the Page model. When a user tries to access a page, you check if their assigned roles include the required permission for that specific page.
For instance, to check if a user is an admin of a specific page:
use App\Models\Page;
use App\Models\User;
// In your controller or service layer
$page = Page::findOrFail($pageId);
$user = auth()->user();
// Check if the user has the 'admin' role assigned to this specific page
if ($user->hasRole('admin') && $user->hasPermissionTo('manage', $page)) {
// Logic proceeds: User is an admin for this page.
}
While you can still use $user->hasRole('admin') for global permissions, the real power comes from iterating through the relationships defined in your pivot tables to determine resource-specific access. This layered approach ensures that authorization logic remains flexible and highly granular, allowing your application to behave exactly as intended, providing robust security foundations necessary for any large-scale Laravel application built on solid principles like those promoted by https://laravelcompany.com.
Conclusion
Achieving multi-role functionality tied directly to specific resources requires moving beyond simple user role assignments. By leveraging Eloquent relationships and pivot tables alongside the powerful foundation provided by Spatie, you can construct a highly flexible and granular authorization system. This method allows your application to replicate complex permission scenarios, giving users the exact access they need for each piece of data they manage.