PHPackages                             adamnicholson/judge - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. adamnicholson/judge

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

adamnicholson/judge
===================

Authorisation library

0.1(8y ago)029.9k↓33%[2 issues](https://github.com/adamnicholson/judge/issues)MITPHP

Since May 23Pushed 8y agoCompare

[ Source](https://github.com/adamnicholson/judge)[ Packagist](https://packagist.org/packages/adamnicholson/judge)[ RSS](/packages/adamnicholson-judge/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (2)Used By (0)

Judge
=====

[](#judge)

Authorization package for PHP.

Getting Started
---------------

[](#getting-started)

### Roles &amp; Identities

[](#roles--identities)

"Roles" are *things* that users of your application can do. These are represented simply as text strings, and are usually things like "EDIT\_ORDERS", "VIEW\_LOGS", etc.

"Identities" represent the users of your application. Like roles, they are represented as a string. An identity could be some account specific key like an email address or user ID, or it could be something completely different like "console" or "API", or even "anonymous".

Keeping this mental separation between accounts and identities is key - Judge doesn't have any knowledge of, or care about, accounts or users.

To get started with some basic role-based auth, there is no setup required. Just instantiate `Judge`, and `allow` an an identity access to a role:

```
$judge = new Judge();

// Grant access to edit orders
$judge->allow('adam@example.com', 'EDIT_ORDERS');
$judge->check('adam@example.com', 'EDIT_ORDERS'); // true

// Revoke access to edit orders
$judge->deny('adam@example.com', 'EDIT_ORDERS');
$judge->check('adam@example.com', 'EDIT_ORDERS'); // false
```

Simple enough? Good, now let's go a little deeper.

### Role Contexts

[](#role-contexts)

Simple role-based permissions suit a lot of use cases, but often you hit their limits quickly when an application starts to grow. Say you have a role for "EDIT\_ORDERS" which applies to all orders, but you need a single identity to have access to only edit 1 specific order. How would you do this?

In Judge, the way you would achieve this is by using role "contexts". A role context is a third parameter you can pass to `allow()`, `deny()` and `check()` to add more specificity to your rule. In practice, a context is usually used for unique identifiers such as an order ID:

```
$judge->allow('adam@example.com', 'EDIT_ORDERS', '5');
$judge->check('adam@example.com', 'EDIT_ORDERS', '5'); // true
```

The benefit of role contexts is due to their ability to inherit rules. If an rule has not been explicity granted/revoked for the exact role+context combination, then Judge will fallback to check if the identity has been granted/revoked for that role *without* the context:

```
$judge = new Judge();

// Grant access to edit all orders
$judge->allow('adam@example.com', 'EDIT_ORDERS');

// Override the above, revoking access specifically to order "10"
$judge->deny('adam@example.com', 'EDIT_ORDERS', '10');

$judge->check('adam@example.com', 'EDIT_ORDERS'); // true
$judge->check('adam@example.com', 'EDIT_ORDERS', '5'); // true
$judge->check('adam@example.com', 'EDIT_ORDERS', '10'); // false
```

### Role Inheritence

[](#role-inheritence)

Roles &amp; contexts together can solve many auth requirements, but larger systems may need more complex inheritance rules. Here is where we introduce role "parents".

Configuring a role parent looks like this:

```
$judge->getRepository()->addRole('{ROLE}', '{PARENT_ROLE}');
```

If you call `check()` but the identity has not been explicitly granted or revoked access to the role, but that role has a defined parent, then we fallback to check if a rule exists for the parent:

```
$judge = new Judge();

// Setup the "EDIT_ORDERS" role with the parent "ORDERS"
$judge->getRepository()->addRole('EDIT_ORDERS', 'ORDERS');

// Grant access to ORDERS and all child roles
$judge->allow('adam@example.com', 'ORDERS');

$judge->check('adam@example', 'EDIT_ORDERS'); // true
```

You can have as many levels in your role parent hierarchy as you like:

```
$judge = new Judge();

$repo = $judge->getRepository();
$repo->addRole('DELETE_ORDERS', 'CHANGE_ORDERS');
$repo->addRole('CHANGE_ORDERS', 'VIEW_ORDERS');
$repo->addRole('VIEW_ORDERS', 'ORDERS');

// Grant access to ORDERS and all children
$judge->allow('adam@example.com', 'ORDERS');

$judge->check('adam@example', 'EDIT_ORDERS'); // true

// Override the above for access to CHANGE_ORDERS and its children recursively
$judge->deny('adam@example.com', 'CHANGE_ORDERS');

$judge->check('adam@example', 'ORDERS'); // true
$judge->check('adam@example', 'VIEW_ORDERS'); // true
$judge->check('adam@example', 'CHANGE_ORDERS'); // false
$judge->check('adam@example', 'DELETE_ORDERS'); // false
```

### Identity Inheritence

[](#identity-inheritence)

Identity inheritence works just like role inheritence:

```
$judge = new Judge();

$repo = $judge->getRepository();
$repo->addIdentity('adam', 'customer_service');

$judge->allow('customer_service', 'EDIT_ORDERS');

$judge->check('adam', 'EDIT_ORDERS'); // true
```

### Putting it all together

[](#putting-it-all-together)

Role contexts, role parents, and identity parents all stack, working together to give a truly robust authorisation system.

In order of precidence:

1. Exact match of the identity-role-context combination passed
2. Parent identities with the same role &amp; context
3. The identity + role passed without any context
4. Parent identities with the same role without any context
5. Parent roles with the original identity
6. Parent roles with parent identities

### Logic Flow

[](#logic-flow)

[![](readme-flow.jpg)](readme-flow.jpg)

### The Data Structure

[](#the-data-structure)

Roles:

RoleParentRoleORDERS\_EDITORDERS\_VIEWORDERS\_VIEWORDERSORDERS`null`Identities:

IdentityParentIdentityadamcustomer\_servicepaulcustomer\_servicecustomer\_service`null`Rules:

IdentityRoleContextStateadamORDERS\_EDIT5GRANTEDcustomer\_serviceORDERS`null`GRANTEDpaulORDERS\_VIEW5REVOKEDPersistence
-----------

[](#persistence)

The main problem with all of the examples so far is that roles &amp; identities are not persisted across requests - meaning you'd need to reconfigure Judge to understand your identity/role hierarchies, and allow/deny all the relevant permissions, on every request.

These rules/roles/identities can be persisted between requests by using a `Judge\Repository\Repository`, which can be passed to `Judge::__construct()` as the first argument.

Judge ships with a number of `Judge\Repository\Repository` implementations to use out of the box:

- `PDORepository` : Store data to a [PDO](http://php.net/manual/en/pdo.drivers.php) compatible DB, like MySQL, SQLite, PostgreSQL
- `FlatbaseRepository` : Store to a [flat file database](https://github.com/adamnicholson/flatbase)
- `ArrayRepository` : Store data in an array for the duration of this request

> If you do not pass a `Repository` to Judge's constructor, then `ArrayRepository` will be used by default.

#### PDORepository

[](#pdorepository)

Store data to a [PDO](http://php.net/manual/en/pdo.drivers.php) compatible DB, like MySQL, SQLite, PostgreSQL

```
$pdo = new PDO('mysql:host=db;dbname=site', 'root');
$repo = new Judge\Repository\PDORepository($pdo);
$judge = new Judge\Judge($repo);
```

You may wish to use the `PDORepository` in conjunction with the `LazyRepositoryWrapper`, so that you do not have to instantiate a `PDO` connection until it is actually requested.

```
$repo = new Judge\Repository\LazyRepositoryWrapper(function () {
    $pdo = new PDO('mysql:host=db;dbname=site', 'root');
    return new Judge\Repository\PDORepository($pdo);
});
$judge = new Judge\Judge($repo);
```

#### ArrayRepository

[](#arrayrepository)

Store data in an in-memory array for the duration of this process.

```
$judge = new Judge\Judge(new ArrayRepository);
```

#### FlatbaseRepository

[](#flatbaserepository)

Store to a [flat file database](https://github.com/adamnicholson/flatbase).

```
$storage = new Flatbase\Storage\Filesystem('/some/storage/path');
$flatbase = new Flatbase\Flatbase($storage);
$repo = new Judge\Repository\FlatbaseRepository($pdo);
$judge = new Judge\Judge($repo);
```

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity27

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

3282d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/bff7c902e927fdfad96739ab558acd367fe0bc689efe400b430e1d8a1aafb0e4?d=identicon)[adamnicholson](/maintainers/adamnicholson)

---

Top Contributors

[![adamnicholson](https://avatars.githubusercontent.com/u/7761178?v=4)](https://github.com/adamnicholson "adamnicholson (31 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/adamnicholson-judge/health.svg)

```
[![Health](https://phpackages.com/badges/adamnicholson-judge/health.svg)](https://phpackages.com/packages/adamnicholson-judge)
```

###  Alternatives

[bezhansalleh/filament-shield

Filament support for `spatie/laravel-permission`.

2.8k2.9M88](/packages/bezhansalleh-filament-shield)[gesdinet/jwt-refresh-token-bundle

Implements a refresh token system over Json Web Tokens in Symfony

70516.4M35](/packages/gesdinet-jwt-refresh-token-bundle)[illuminate/auth

The Illuminate Auth package.

9327.3M1.0k](/packages/illuminate-auth)[beatswitch/lock

A flexible, driver based Acl package for PHP 5.4+

870304.7k2](/packages/beatswitch-lock)[amocrm/amocrm-api-library

amoCRM API Client

182728.5k6](/packages/amocrm-amocrm-api-library)[vonage/jwt

A standalone package for creating JWTs for Vonage APIs

424.1M4](/packages/vonage-jwt)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
