NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Assign through Permissions::for($holder). assignRole is additive and variadic, removeRole detaches, and syncRoles makes the given set the exact role set:

use RoundlyConsulting\Permissions\Facades\Permissions;

Permissions::for($user)->assignRole('administrator');
Permissions::for($user)->assignRole('editor', 'reviewer');   // variadic, additive
Permissions::for($user)->assignRole(['editor', $role]);      // arrays, Role models, backed enums

Permissions::for($user)->removeRole('administrator');
Permissions::for($user)->syncRoles(['editor']);              // exact role set
Permissions::for($user)->forgetAllAuthorization();           // every role and direct grant

Names, backed enums, Role models, arrays and nested iterables are all accepted. An unknown role name throws RoleDoesNotExist; an unsaved Role model throws PermissionException. syncRoles runs in a transaction, so a concurrent check never sees an empty mid-sync role set.

Role writes need a holder with HasRoles — Permissions::for($role)->assignRole() throws a PermissionException, because a Role holds permissions, never roles. On the model, the HasRoles verbs are shorthand for the same calls:

$user->assignRole('administrator');
$user->removeRole('administrator');
$user->syncRoles(['editor']);
$user->forgetAllAuthorization();

Inheriting permissions through roles

Grant permissions to a role once and every holder inherits them. Change the role and every holder updates — no per-user writes:

use RoundlyConsulting\Permissions\Facades\Permissions;

Permissions::permission('articles.publish');
Permissions::for(Permissions::role('editor'))->givePermissionTo('articles.publish');

Permissions::for($user)->assignRole('editor');
$user->hasPermissionTo('articles.publish'); // true — inherited via the role

Removing everything

Permissions::for($holder)->forgetAllAuthorization() detaches every role and every direct permission in one transaction. Use it when a holder is deleted — see Deleting holders.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.