vaened/php-sentinel
Composer 安装命令:
composer require vaened/php-sentinel
包简介
A framework-agnostic authorization Core for PHP. Roles and permissions with deny-overrides-grant precedence built in.
README 文档
README
Framework-agnostic authorization core for PHP 8.4+.
Installation
composer require vaened/php-sentinel
Requires PHP 8.4 or higher. Its only dependency is vaened/support.
Quick start
// Registry: handled by a seeder or your admin UI $admin = $roleRegistry->create('admin', 'Administrator'); $edit = $permissionRegistry->create('posts.edit', 'Edit Posts'); // Assignment $granter->grant($admin, $edit); $granter->grant($user, $admin); // Evaluation $authorizer->can($user, ['posts.edit']); // true $authorizer->is($user, ['admin']); // true // Deny overrides inherited grant $denier->deny($user, $edit); $authorizer->can($user, ['posts.edit']); // false // Revoke clears any denial or previous assignment $revoker->revoke($user, $edit); $authorizer->can($user, ['posts.edit']); // true again
The example assumes concrete model and persistence implementations are already wired in your application bootstrap.
Integration surface
Sentinel provides the Authorizer, the operators, and the Registry
services, including the concrete PermissionEntryProvider and
RoleEntryProvider.
The package consumer implements the domain and repository contracts.
Foundations
These contracts define the minimum model Sentinel needs to evaluate authorization.
-
Subject
- Contract:
Subject - Represents the subject requesting permissions.
- Sentinel only requires:
id(): int|string|IdentifierIdentifier:Identifier
- Contract:
-
Authorization
- Contract:
Authorization - Defines:
id(): int|stringcode(): stringname(): stringdescription(): ?string
RoleandPermissionexpose scalar identity.- Derived contracts:
- Role
- Contract:
Role - Represents a composite authorization. A role groups permissions.
- Contract:
- Permission
- Contract:
Permission - Represents an atomic authorization.
- Contract:
- Role
- Contract:
Repositories
Repositories persist both the catalog and the relationships between subjects, roles, and permissions.
-
RoleRepository
- Contract:
RoleRepository - Stores role records with
id,code,name, anddescription.
- Contract:
-
PermissionRepository
- Contract:
PermissionRepository - Stores permission records with
id,code,name, anddescription.
- Contract:
-
SubjectRoleRepository
- Contract:
SubjectRoleRepository - Persists
subject ↔ rolelinks.
- Contract:
-
SubjectPermissionRepository
- Contract:
SubjectPermissionRepository - Persists
subject ↔ permissionlinks. - Each assignment exposes
isDenied().
- Contract:
-
RolePermissionRepository
- Contract:
RolePermissionRepository - Persists
role ↔ permissionlinks. - Roles only grant permissions; they do not support explicit denials.
- Contract:
Each repository exposes the combination of lookup, grants, exists, allOf, create, update, and remove that belongs to its
own contract.
Entry providers
The entry providers are concrete core services. They compose repositories and return the entries consumed by the Authorizer.
-
PermissionEntryProvider
- Service:
PermissionEntryProvider - Encodes the effective precedence of permissions.
- Invariants:
- it only returns codes that were requested;
- for a subject, direct permissions are resolved first and missing codes are completed through role grants;
- deny overrides inherited grant: a direct denial on the subject overrides any permission inherited from a role;
- for a role, effective permissions are the role's direct permissions.
- Service:
-
RoleEntryProvider
- Service:
RoleEntryProvider - Resolves which requested role codes are effectively assigned to the subject.
- It does not define precedence rules.
- Service:
Implementation references
- Reference wiring:
tests/Integration/AuthorizerFlowTest.php - Reference in-memory implementations:
tests/Runtime/ - In-memory repositories:
tests/Runtime/Repositories/ - Core
PermissionEntryProvider:src/Authorization/PermissionEntryProvider.php - Core
RoleEntryProvider:src/Authorization/RoleEntryProvider.php
Authorizer
Authorizer is the read gate. It combines a PermissionEntryProvider and a RoleEntryProvider and
answers boolean questions about a Subject or a Role. It is constructed once with both providers and is then ready to answer can,
cannot, is, and isnt at any time.
can()
Returns true when the owner has at least one of the requested permissions, or all of them when you pass Junction::And.
$owner:Subject|Role— the entity being evaluated.$permissions:array<string>— the permission codes to evaluate. Always an array, never a bare string.$junction:Junction(default:Junction::Or) — the combinator.
cannot()
Inverse of can(). Same signature.
is()
Returns true when the subject has at least one of the requested roles, or all of them when you pass Junction::And. Unlike can, it only
accepts Subject as an owner, not Role.
$subject:Subject— the subject being evaluated.$roles:array<string>— the role codes to evaluate.$junction:Junction(default:Junction::Or) — the combinator.
isnt()
Inverse of is(). Same signature.
Junction
Enum with two cases:
Junction::Or(default) — one match is enough.Junction::And— every code must be allowed.
Operators
The three operators mutate state through your repositories. All of them are variadic, so they can attach or detach multiple items in a single call.
Granter
Granter grants assignments.
$granter->grant($user, $admin); // user has the admin role $granter->grant($admin, $edit, $delete); // admin role has two permissions $granter->grant($user, $admin, $edit, $delete); // everything in one call
It accepts Subject or Role as owner. If it receives a Role as owner and another Role as authorization, it throws
InvalidAuthorization: roles cannot contain other roles.
Denier
Denier explicitly denies permissions to a subject. It applies the central rule: a direct denial overrides any
inherited permission.
$denier->deny($user, $edit); $denier->deny($user, $edit, $delete); // variadic
It only accepts Subject as an owner. Roles do not support denials.
Revoker
Revoker removes any previous assignment, whether it was a grant or a denial. It is idempotent: if the
assignment does not exist, it makes no changes.
$revoker->revoke($user, $admin); $revoker->revoke($user, $edit, $delete);
It accepts Subject or Role as owner.
Registry
PermissionRegistry and RoleRegistry manage the registration
operations for each entity: create, update, and remove.
$roleRegistry = new RoleRegistry($roleRepository, $subjectRoleRepository); $permissionRegistry = new PermissionRegistry($permissionRepository, $subjectPermissionRepository, $rolePermissionRepository); $admin = $roleRegistry->create('admin', 'Administrator'); $roleRegistry->update($admin->id(), 'Administrator', 'Full access'); $roleRegistry->remove($admin->id());
create()returns the entity with its assigned id. It throws*AlreadyExistswhen the code already exists.update()operates by id. Passingnullas description clears it.remove()is idempotent: if the id does not exist, it makes no changes. If the entity is in use, it throws*InUse.
Errors
All exceptions thrown by Sentinel extend AuthorizationError, which itself extends RuntimeException.
To catch any Sentinel error:
try { $roleRegistry->create('admin', 'Administrator'); } catch (AuthorizationError $e) { // covers PermissionAlreadyExists, RoleNotFound, PermissionInUse, etc. }
Specific exceptions:
| Exception | Thrown when |
|---|---|
PermissionAlreadyExists |
PermissionRegistry::create receives a code that already exists. |
RoleAlreadyExists |
RoleRegistry::create receives a code that already exists. |
PermissionNotFound |
PermissionRegistry::update or an operator cannot find the id/code. |
RoleNotFound |
RoleRegistry::update or an operator cannot find the id/code. |
PermissionInUse |
PermissionRegistry::remove detects a linked subject or role. |
RoleInUse |
RoleRegistry::remove detects a subject linked to that role. |
InvalidAuthorization |
Granter receives roles as targets from an owner that is also a role. |
Development
make composer-install
make test
Additional documentation
You can find more details in the source code as well as in the tests located in tests/.
The tests cover different usage scenarios and can serve as additional reference for understanding the library’s behavior.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-08