ssntpl/laravel-acl is a Laravel package for laravel acl package..
It currently has 3 GitHub stars and 799 downloads on Packagist (latest version v0.2.1).
Install it with composer require ssntpl/laravel-acl.
Discover more Laravel packages by ssntpl
or browse all Laravel packages to compare alternatives.
Last updated
Laravel ACL is a framework-agnostic access control layer for Laravel 10/11/12 projects. It provides global and resource-scoped roles, explicit ALLOW/DENY permissions, permission implication trees, and cache-friendly lookups that plug straight into your existing Eloquent models through a reusable trait.
HasRoles) for Eloquent subjects.acl:cache-reset artisan command.composer require ssntpl/laravel-acl
php artisan vendor:publish --tag=acl-config
php artisan vendor:publish --tag=acl-migrations
php artisan migrate
config/acl.php)return [
'cache_ttl' => env('ACL_CACHE_TTL', 86400),
];
cache_ttl – lifetime (seconds) for cached permission trees and role lookups.Publishing the migration adds:
| Table | Key columns | Purpose |
| --- | --- | --- |
| acl_roles | name, resource_type, description | Defines each role; resource_type is null for global roles. |
| acl_permissions | name, resource_type | Defines permissions; names are unique. |
| acl_role_permissions | role_id, permission_id, effect | Pivot with ALLOW/DENY effect per permission. |
| acl_role_assignments | subject_type, subject_id, role_id, optional resource_*, expires_at | Links a subject (e.g., user) to a role, optionally scoped to a resource, with expiration support. |
| acl_permissions_implications | parent_permission_id, child_permission_id | Models permission implication trees (grant parent ⇒ grant child). |
HasRoles to the authenticatable modelnamespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Ssntpl\LaravelAcl\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
}
Interactive artisan flow:
php artisan acl:create-permission articles.publish "App\\Models\\Project" --implied="articles.read|articles.list"
Programmatically:
use Ssntpl\LaravelAcl\Models\Permission;
$publish = Permission::create(['name' => 'articles.publish']);
$read = Permission::firstOrCreate(['name' => 'articles.read']);
$publish->children()->attach($read); // Publish implies read
php artisan acl:create-role admin "App\\Models\\Project" "articles.read|articles.publish|comments.moderate"
In PHP you can use either syncPermissions() (implicit ALLOW) or syncPermissionsWithEffect():
use Ssntpl\LaravelAcl\Models\Role;
$role = Role::firstOrCreate([
'name' => 'admin',
'resource_type' => App\Models\Project::class,
]);
$role->syncPermissionsWithEffect([
$publish->id => 'ALLOW',
$read->id => 'ALLOW',
]);
Using the trait:
$user = User::find(1);
$project = Project::find(42);
$user->assignRole('admin', $project); // scoped role
$user->assignRole('super-admin', null, now()->addMonth()); // global role with expiration
Using the command (handy for ops/support teams):
php artisan acl:assign-role admin App\\Models\\User:1 App\\Models\\Project:42 --expires-at="2025-12-31 23:59:59"
if ($user->hasRole('admin', $project)) {
// subject is an admin of this project
}
$role = $user->getRole(); // global role assignment (resource = null)
if ($role && $role->can('articles.publish')) {
// allowed via direct or implied permission (and not explicitly denied)
}
removeRole($resource = null) deletes an assignment, and calling getRole($resource) returns the underlying Role model instance if one exists and is not expired.
Register the middleware aliases in app/Http/Kernel.php:
protected $middlewareAliases = [
'check_global_role' => \Ssntpl\LaravelAcl\Http\Middleware\CheckGlobalRole::class,
'check_global_permission' => \Ssntpl\LaravelAcl\Http\Middleware\CheckGlobalPermission::class,
];
Usage:
Route::get('/admin', fn () => 'ok')->middleware('check_global_role:admin|manager');
Route::post('/articles', fn () => 'ok')->middleware('check_global_permission:articles.publish|articles.create');
Both middleware assume global assignments (resource is null) when evaluating the authenticated subject.
The authenticated guard’s model must use the
HasRolestrait (or at least expose compatiblehasRole/getRolemethods) because the middleware works directly withAuth::user()without re-querying the database.
Role permissions and implied permission trees are cached per record using the configured TTL. Cache invalidation happens automatically when:
acl:cache-reset command is executed.Run a full reset manually with:
php artisan acl:cache-reset
| Command | Description |
| --- | --- |
| acl:create-permission | Create/update a permission and optionally attach implied permissions (supports interactive prompts). |
| acl:create-role | Create a role and assign permissions in one step. |
| acl:assign-role | Attach a role to a subject/resource pair with optional expiration. |
| acl:cache-reset | Flush cached permissions and role lookups. |
PRs are welcome. Please include reproduction steps or tests when reporting/patching bugs.