Checking access
Reads live on the model, not the facade — they use the relations you may have eager-loaded. The facade answers only catalog questions, such as Permissions::exists():
$user->hasRole('administrator'); // bool
$user->hasRole(['administrator', 'editor']); // any of
$user->hasPermissionTo('auth.users.view'); // effective: direct or via a role
$user->getRoleNames(); // Collection<string>
$user->getPermissionNames(); // Collection<string> — direct grants only
$user->getDirectPermissions(); // direct grants only
$user->getAllPermissions(); // direct ∪ via-roles, de-duped — the JWT claim source
$user->getAllPermissions()->pluck('name');- hasRole() — true when the model holds any of the given roles (a string, an enum, or an iterable of names, enums and Role models).
- hasPermissionTo() — on a holder, checks effective permissions: direct grants plus everything inherited through roles. On a Role, it checks the role’s own grants.
- getDirectPermissions() / getPermissionNames() — direct grants only.
- getAllPermissions() — direct ∪ via-roles, de-duplicated by id.
Checks never throw: an unknown role or permission name simply returns false.
Eager loading
Checks read the loaded relations when they are present. Eager-load roles.permissions and permissions to check many holders without N+1 queries — the result is identical eager or lazy:
$users = User::query()->with(['roles.permissions', 'permissions'])->get();
foreach ($users as $user) {
$user->getAllPermissions(); // read from the loaded relations — no extra queries
}Permission claims for tokens
In an API service, getAllPermissions() is the natural source for a token’s permissions claim:
$claims = [
'roles' => $user->getRoleNames()->all(),
'permissions' => $user->getAllPermissions()->pluck('name')->all(),
];Query scope
Filter holders by role with the role() scope — it matches models that hold any of the given roles:
User::query()->role('administrator')->count();
User::query()->role(['administrator', 'editor'])->get();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 cryptoBy 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.