hosseinhezami/laravel-permission-manager
Installation:
composer require hosseinhezami/laravel-permission-manager
php artisan permission-manager:install
This publishes the migration, config, and blade directives.
Run Migrations:
php artisan migrate
Creates roles, permissions, and model_has_roles tables.
First Use Case: Assign a role to a user and check permissions in a controller:
use App\Models\User;
use Spatie\Permission\Models\Role;
use Hosseinhezami\PermissionManager\PermissionManager;
// Assign role to user
$user = User::find(1);
$user->assignRole('admin');
// Check permission (e.g., 'users.index')
if (PermissionManager::check('users.index')) {
// User has permission
}
Blade Directives:
Use @can/@cannot in views:
@can('users.index')
<a href="{{ route('users.index') }}">View Users</a>
@endcan
Role Assignment:
// Single role
$user->assignRole('editor');
// Multiple roles
$user->assignRole(['admin', 'moderator']);
// Remove role
$user->removeRole('editor');
Permission Management:
// Assign permission to role
$role = Role::findByName('admin');
$role->givePermissionTo('users.index');
// Assign wildcard permission (e.g., all 'users.*' routes)
$role->givePermissionTo('users.*');
// Check permission (user or role)
if (PermissionManager::check('users.create')) {
// ...
}
Route-Based Permissions:
Define middleware in app/Http/Kernel.php:
protected $routeMiddleware = [
'permission' => \Hosseinhezami\PermissionManager\Middleware\PermissionMiddleware::class,
];
Apply to routes:
Route::get('/users', [UserController::class, 'index'])->middleware('permission:users.index');
Fluent API for Bulk Operations:
// Create role with permissions
$role = Role::create(['name' => 'admin']);
$role->givePermissionTo(['users.index', 'users.create', 'users.*']);
// Sync permissions (replace existing)
$role->syncPermissions(['users.index', 'reports.view']);
Blade Integration:
@can('users.index')
<button>Manage Users</button>
@else
<button disabled>No Access</button>
@endcan
Artisan Commands:
# Create role
php artisan permission-manager:role admin
# Create permission
php artisan permission-manager:permission users.index
# Assign permission to role
php artisan permission-manager:permission-to-role users.index admin
Seeding Permissions:
Use DatabaseSeeder to predefine roles/permissions:
public function run()
{
$admin = Role::create(['name' => 'admin']);
$admin->givePermissionTo(['users.*', 'posts.*']);
$user = User::find(1);
$user->assignRole('admin');
}
Dynamic Permissions: Generate permissions dynamically based on route names:
$routeName = 'users.index';
if (PermissionManager::check($routeName)) {
// ...
}
Wildcard Strategy:
Use wildcards for broad access (e.g., admin.* for all admin routes) but avoid over-permissive patterns like *.
Middleware for API: Extend the middleware for API gateways:
public function handle($request, Closure $next, $permission)
{
if (!PermissionManager::check($permission)) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
Caching:
Enable caching for performance (configurable in config/permission-manager.php):
'cache' => [
'enabled' => true,
'driver' => 'redis',
],
Wildcard Overuse:
* or *.* can lead to unintended access.admin.*) and audit permissions regularly.Route Name Mismatches:
resource.verb.collection).Caching Conflicts:
php artisan cache:clear
Middleware Misconfiguration:
app/Http/Kernel.php and route definitions.Blade Directive Scope:
@can directives evaluate in the context of the authenticated user.Permission Checks: Log permission checks for debugging:
if (PermissionManager::check('users.index')) {
\Log::info('Permission granted: users.index');
}
Role Assignment: Verify roles with:
$user->roles; // Collection of assigned roles
$user->getAllPermissions(); // All permissions (direct + via roles)
Artisan Errors: If commands fail, check:
php artisan permission-manager:list-roles
php artisan permission-manager:list-permissions
Custom Permission Models:
Extend the Permission model for additional fields:
class CustomPermission extends \Spatie\Permission\Models\Permission
{
protected $casts = [
'is_active' => 'boolean',
];
}
Permission Gates: Combine with Laravel’s gates for hybrid logic:
Gate::define('delete-post', function ($user, $post) {
return $user->hasPermissionTo('posts.delete') && $post->user_id === $user->id;
});
Event Listeners: Listen for role/permission changes:
// Event: RoleAssigned
// Event: PermissionGiven
Policy Integration: Use policies alongside permissions:
class PostPolicy
{
public function update(User $user, Post $post)
{
return $user->hasPermissionTo('posts.update');
}
}
Custom Blade Directives: Extend directives for complex logic:
Blade::if('canAdmin', function ($view, $permission) {
return auth()->check() && auth()->user()->hasRole('admin');
});
Usage:
@canAdmin
Admin Panel
@endcanAdmin
Permission Naming:
Use kebab-case (e.g., users.index) for consistency with Laravel’s route naming.
Case Sensitivity: Permissions are case-sensitive by default. Normalize case if needed:
$permission = strtolower('Users.Index'); // 'users.index'
Default Guard:
Ensure permission-manager.php uses the correct guard (e.g., web):
'guard_name' => 'web',
Model Binding:
For non-standard models, bind the PermissionManager to your user model:
class User extends Authenticatable
{
public function getPermissionsAttribute()
{
return $this->getAllPermissions()->pluck('name');
}
}
How can I help you explore Laravel packages today?