bonnier/role-provider
Laravel package that provides roles via a provider layer, helping define, expose, and resolve user roles in your app. Intended for simple role handling and integration points where a central role source is needed.
Installation
composer require bonnier/role-provider
Publish the migration and config:
php artisan vendor:publish --provider="Bonnier\RoleProvider\RoleProviderServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="Bonnier\RoleProvider\RoleProviderServiceProvider" --tag="config"
Run the migration:
php artisan migrate
Basic Usage
Attach a role to a user (e.g., User model):
use Bonnier\RoleProvider\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
}
Assign a role to a user:
$user = User::find(1);
$user->attachRole('admin'); // 'admin' must exist in the `roles` table
First Use Case Check if a user has a role in a controller/middleware:
if (auth()->user()->hasRole('admin')) {
// Grant access
}
Dynamic Role Assignment Useful for registration flows:
$user = User::create([...]);
$user->attachRole('subscriber'); // Default role
Bulk Role Assignment Assign roles to multiple users via query:
User::where('is_premium', true)->each(function ($user) {
$user->attachRole('premium');
});
Role-Based Middleware Create middleware to restrict routes:
namespace App\Http\Middleware;
use Closure;
use Bonnier\RoleProvider\Traits\HasRoles;
class RoleMiddleware
{
public function handle($request, Closure $next, $role)
{
if (!auth()->user()->hasRole($role)) {
abort(403);
}
return $next($request);
}
}
Register in app/Http/Kernel.php:
protected $routeMiddleware = [
'role' => \App\Http\Middleware\RoleMiddleware::class,
];
Use in routes:
Route::get('/admin', function () { ... })->middleware('role:admin');
Extend Laravel’s authorization system:
use Bonnier\RoleProvider\Traits\HasRoles;
class PostPolicy
{
public function update(User $user, Post $post)
{
return $user->hasRole('editor') || $user->id === $post->user_id;
}
}
Since the package lacks built-in hierarchy, implement logic in policies:
public function canAccessDashboard(User $user)
{
return $user->hasRole('admin') || $user->hasRole('manager');
}
Missing Role Records
Ensure roles exist in the roles table before attaching:
$role = \Bonnier\RoleProvider\Models\Role::firstOrCreate(['name' => 'admin']);
$user->attachRole($role);
Detaching Roles
Use detachRole() to remove roles:
$user->detachRole('admin');
Warning: No cascade deletion—orphaned role records remain.
Performance with Large Datasets
Avoid hasRole() in loops for users with many roles. Cache role checks:
$roles = auth()->user()->roles->pluck('name');
if ($roles->contains('admin')) { ... }
Role Not Found Errors
Verify the role name matches the roles table exactly (case-sensitive).
Check for typos or whitespace:
$role = \Bonnier\RoleProvider\Models\Role::where('name', 'LIKE', '%admin%')->first();
Middleware Failing Silently Add logging to debug:
public function handle($request, Closure $next, $role)
{
\Log::debug('Checking role: ' . $role, ['user_roles' => auth()->user()->roles->pluck('name')]);
if (!auth()->user()->hasRole($role)) {
abort(403, 'Unauthorized: Missing role "' . $role . '"');
}
return $next($request);
}
Custom Role Model
Extend the Role model (e.g., add description):
php artisan make:model RoleExtension -m
Update the migration and model:
class Role extends \Bonnier\RoleProvider\Models\Role
{
protected $fillable = ['name', 'description'];
}
Role Events Listen for role attachment/detachment:
\Bonnier\RoleProvider\Models\Role::attached(function ($user, $role) {
\Log::info("User {$user->id} assigned role {$role->name}");
});
API Responses Serialize roles in JSON responses:
return response()->json([
'user' => auth()->user()->load('roles')->append('role_names'),
]);
Add to User model:
public function getRoleNamesAttribute()
{
return $this->roles->pluck('name');
}
Table Names
Customize in config/role-provider.php:
'tables' => [
'roles' => 'custom_roles',
'role_user' => 'custom_role_user',
],
Run migrations after changes.
Pivot Table
The package uses a role_user pivot table by default. Ensure your User model’s roles() relationship matches:
public function roles()
{
return $this->belongsToMany(\Bonnier\RoleProvider\Models\Role::class, 'role_user');
}
How can I help you explore Laravel packages today?