Download the PHP package saadmajeed/laravel-entitlements without Composer

On this page you can find all versions of the php package saadmajeed/laravel-entitlements. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-entitlements

Laravel Entitlements

A feature/entitlement engine for Laravel 11, 12, and 13. Define plans, features, limits, metered usage, and conditional access rules — then check them anywhere in your app.

Features

Installation

Publish the config and migrations:

Or run everything in one step:

Configuration

See config/entitlements.php for all options:

Key Default Description
cache.store array Cache store for entitlement decisions (use redis/database in production)
cache.ttl 3600 Cache TTL in seconds
cache.prefix ent: Cache key prefix
usage.enabled true Enable synchronous, transactional usage tracking
audit.enabled true Enable audit logging
middleware.default_http_code 403 HTTP status when entitlement check fails
default_subject_model null Default model for artisan command

Quick Start

1. Add the trait to your subject

The HasPlan trait adds a plan() relationship and convenience methods.

2. Create a plan

Assign the plan to a user:

3. Create entitlements

4. Assign values to a plan

4b. Define a plan fluently (recommended)

The manual steps above are fine, but the fluent Entitlements facade hides the pivot-format details and keeps your seeding idempotent:

You can also pass a callback instead of chaining:

Entitlements::plan() finds-or-creates the Plan and each referenced Entitlement, then updates the per-plan pivot value on every run — so it is safe to call from a seeder over and over. A full example plan tree lives in database/seeders/EntitlementsSeeder.php.

Removing entitlements

To revoke an entitlement from a plan, detach it (the global Entitlement row is kept so other plans can still use it):

5. Check entitlements

value() is a convenience getter for the resolved value of why($key)->value. consume() is an alias of use() for recording metered/limit usage.

Entitlement Types

Boolean

Simple on/off feature flag. The pivot value should be ['enabled' => true] or ['enabled' => false].

Limit

A numeric cap. The value is a number or ['max' => N].

Metered

Countable usage that resets on a period (daily, monthly, yearly).

Soft limits

Set soft_limit: true in the entitlement's metadata to allow usage beyond the limit (fires event instead of throwing):

An LimitReached event is fired, but the use() call succeeds.

Time-based

A feature that expires at a specific date.

If expired, an ExpiredEntitlementException is thrown.

Conditional

Access depends on subject attributes.

Supported operators: =, ==, ===, !=, !==, <>, >, >=, <, <=, in, not_in, contains.

Security: by default conditional rules may read any subject attribute. To restrict which attributes rules may reference, set conditional.allowed_fields in config/entitlements.php. When the allowlist is non-empty, any rule referencing a field outside it causes that conditional entitlement to be denied ("deny unknown"). You can also provide a custom conditional.attribute_resolver (a class implementing SaadMajeed\Entitlements\Contracts\AttributeResolver) to control how attribute values are read.

Config

A generic configuration value (always allowed, returns the raw value).

Plan Inheritance

Plans can have a parent. Child plans inherit entitlement values from the parent unless overridden.

The resolution pipeline checks:

  1. Per-subject override (if any)
  2. Expiry (for time-based)
  3. Conditional rules
  4. Subject's direct plan value
  5. Parent plan chain (walk up)
  6. Entitlement's default value

Overrides

Override an entitlement for a specific subject:

Overrides have the highest priority in the resolution pipeline. They can optionally expire.

Caching

Entitlement decisions are cached per subject per key. The cache is automatically invalidated when:

Manually flush the cache:

Warm the cache:

Events

Event Payload Fired when
EntitlementChecked subject, entitlement, allowed After any entitlement check
LimitReached subject, entitlement, used, limit, soft When a limit is hit
OverrideApplied override Override created/updated/deleted
PlanChanged subject Subject's plan changes
UsageRecorded subject, entitlement, amount Usage recorded

Listeners are auto-registered to invalidate the cache on OverrideApplied, PlanChanged, and UsageRecorded.

Usage Tracking

Usage is recorded synchronously and atomically — no queue, no background jobs. When you call use(), a single database transaction:

  1. Acquires a per-entitlement named advisory lock (serializing concurrent consumers on MySQL/PostgreSQL),
  2. Inserts the UsageRecord row,
  3. Reads and increments the UsageSummary for the current period inside a SELECT ... FOR UPDATE row lock,
  4. Checks the limit (hard limit rejects with LimitExceededException; soft limit records but fires LimitReached),
  5. Commits — and only then fires the LimitReached event outside the transaction.

Because the read-modify-write of the summary happens under a lock within one transaction, there is no double-counting and no lost update even under high concurrency.

For real-time accuracy, you can query remaining usage directly:

Concurrency

Usage recording is safe under concurrency on MySQL and PostgreSQL, where it uses a named advisory lock plus SELECT ... FOR UPDATE row locking, with automatic retry on deadlock (up to 3 attempts). SQLite is single-writer, so it is also safe but does not exercise the lock paths. The package ships with a parallel-consumer test (tests/Concurrency) that is run against real MySQL/PostgreSQL in CI.

API Reference

Entitlement::for($subject)

Returns a cloned EntitlementManager scoped to the subject.

Method Returns Description
can(string $key) bool Check if an entitlement is allowed
canMany(array $keys) array<string, bool> Check multiple entitlements
limit(string $key) ?float Get the numeric limit value
remaining(string $key) ?float Get remaining usage
use(string $key, float $amount = 1, array $metadata = []) Decision Record usage
consume(string $key, float $amount = 1, array $metadata = []) Decision Alias of use()
value(string $key) mixed Resolved value (why($key)->value)
why(string $key) Explanation Get full resolution trace (debugging)
flushCache(?string $key = null) void Clear cached decisions

Entitlements facade (defining plans)

Method Returns Description
Entitlements::plan(string $slug, ?callable $callback = null) PlanBuilder Find-or-create a plan and define its entitlements fluently

The returned PlanBuilder exposes feature(), limit(), meter(), conditional(), time(), and parent() — all chainable and idempotent — plus remove(), removeMany(), only() (keep only the given keys), and withoutParent(), for revoking entitlements and clearing inheritance.

HasPlan trait methods

Method Returns Description
$subject->can(string $key) bool Delegates to Entitlement::for($subject)->can()
$subject->limit(string $key) ?float Delegates to Entitlement::for($subject)->limit()
$subject->remaining(string $key) ?float Delegates to Entitlement::for($subject)->remaining()
$subject->use(string $key, float $amount = 1) Decision Delegates to Entitlement::for($subject)->use()
$subject->consume(string $key, float $amount = 1) Decision Alias of use()
$subject->value(string $key) mixed Resolved value
$subject->why(string $key) Explanation Delegates to Entitlement::for($subject)->why()
$subject->entitlement(string $key) FluentEntitlement Fluent API gateway

Decision object

Property Type Description
allowed bool Whether access is granted
key string The entitlement key
value mixed The resolved value
type string Entitlement type
source ?string Where the value came from (plan, override, default, etc.)
limit ?float The numeric limit (if applicable)
used ?float Current usage (if metered/limit)
remaining ?float Remaining usage (if metered/limit)
overLimit bool Whether the limit is exceeded
softLimit bool Whether a soft limit is active
expiresAt ?CarbonInterface Expiration date (if time-based)
expired bool Whether the entitlement has expired
path array Resolution steps taken

Explanation object (from why())

A detailed trace of how an entitlement was resolved, including:

Artisan Commands

The subject argument accepts ModelClass:id syntax (e.g. User:1, App\Models\User:42).

entitlement:explain prints the same resolution trace as why() but in a readable form — the final result (ALLOWED / DENIED), the source, plan, override, expiry and usage details, and the ordered resolution steps. Pass --json to get the raw Explanation as JSON (identical to entitlement:check).

Middleware

Protect routes with the entitlement middleware:

If the subject (authenticated user) doesn't have the entitlement, the middleware aborts with 403 (or redirects if a redirect path is provided).

Blade Directive

Requires the user to be authenticated.

Exceptions

Exception HTTP status When thrown
EntitlementNotFoundException n/a Entitlement key not found in database
ExpiredEntitlementException n/a Time-based entitlement has expired
LimitExceededException n/a Hard limit exceeded (has key, limit, used, attempted)

Extend your exception handler to map these to HTTP codes as needed:

Testing

The suite runs against SQLite by default:

Concurrency tests (parallel consumers, advisory/row locking) run against real MySQL / PostgreSQL and are isolated in their own process:

The CI matrix covers Laravel 11, 12, and 13 across MySQL 8.4 and PostgreSQL 16.


All versions of laravel-entitlements with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/support Version ^11.0|^12.0|^13.0
illuminate/database Version ^11.0|^12.0|^13.0
illuminate/container Version ^11.0|^12.0|^13.0
illuminate/cache Version ^11.0|^12.0|^13.0
illuminate/queue Version ^11.0|^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package saadmajeed/laravel-entitlements contains the following files

Loading the files please wait ...