yaroslavpopovic/laravel-policy-soft-cache

Fork of innoge/laravel-policy-soft-cache that keys cache entries by spl_object_id, removing the json_encode + sha512 overhead for high-volume policy checks.

Maintainers

Package info

github.com/yaroslavpopovic/laravel-policy-soft-cache

pkg:composer/yaroslavpopovic/laravel-policy-soft-cache

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 0

v2.0.1 2026-05-14 18:10 UTC

This package is auto-updated.

Last update: 2026-05-14 18:11:02 UTC


README

Latest Version on Packagist

This is a fork of innoge/laravel-policy-soft-cache by Tim Geisendörfer. All credit for the original design, API, and implementation goes to the upstream author. This fork only diverges on the cache-key strategy — see below.

Optimize your Laravel application's performance with soft caching for policy checks. This package caches policy invocations to prevent redundant checks within the same request lifecycle, enhancing your application's response times.

Why this fork

The upstream package keys its in-memory cache by hashing every argument with hash_hmac('sha512', json_encode($args), config('app.key')). That's robust against in-request model mutations (any attribute change invalidates the key automatically), but on workloads that perform many policy checks per request — for example a Filament 5 table where each row renders an ActionGroup with 7+ actions and Filament re-evaluates isVisible() / isDisabled() / isAuthorized() multiple times per action — the key generation cost alone becomes the bottleneck.

In a real-world Filament list page (≈40 records, ~760 Gate::check calls during a single unmountAction re-render), we measured:

Key strategy Cost per Gate::check Overhead for the whole request
hash_hmac('sha512', json_encode($args), app.key) (upstream) ~0.72 ms ~550 ms
spl_object_id($model) (this fork) ~0.0003 ms <1 ms

End-to-end the difference moved the same Livewire unmountAction request from 9.95 s → 6.6 s in the application that motivated the fork.

This fork swaps the key strategy: object arguments are fingerprinted by get_class($obj).':'.spl_object_id($obj), scalars are stringified, and non-Eloquent objects/arrays still fall back to a fast xxh3 hash. The cache is hit only for the same in-memory instance — which is what Filament (and most rendering loops) actually pass during a single render, so the practical hit rate is unchanged for the use case the package was built for.

If you need staleness-on-mutation semantics (the cache key invalidating when a model attribute changes within the same request) please use the upstream package — that's exactly what its json strategy is for.

Requirements

PHP ≥ 8.1, Laravel 9 / 10 / 11 / 12 / 13.

Installation

composer require yaroslavpopovic/laravel-policy-soft-cache

Optionally publish the config file:

php artisan vendor:publish --provider="Innoge\LaravelPolicySoftCache\LaravelPolicySoftCacheServiceProvider"
return [
    /*
     * When enabled, the package will cache the results of all Policies in your Laravel application
     */
    'cache_all_policies' => env('CACHE_ALL_POLICIES', true),
];

Usage

By default, all policy calls are cached for the lifetime of the current request. To opt in selectively instead, set CACHE_ALL_POLICIES=false and mark the policies you want cached with Innoge\LaravelPolicySoftCache\Contracts\SoftCacheable:

use Innoge\LaravelPolicySoftCache\Contracts\SoftCacheable;

class UserPolicy implements SoftCacheable
{
    // ...
}

Clearing the cache

\Innoge\LaravelPolicySoftCache\LaravelPolicySoftCache::flushCache();

Known issues

Gate::before and Service Provider load order

If your application registers a Gate::before callback (typically in AuthServiceProvider), Laravel's package auto-discovery may load this provider before yours, which means your Gate::before runs first and can short-circuit the cache. To enforce explicit load order, register the provider manually and disable auto-discovery for this package:

  1. Add \Innoge\LaravelPolicySoftCache\LaravelPolicySoftCacheServiceProvider::class at the end of bootstrap/providers.php (Laravel 11+) or config/app.php providers array.

  2. In your composer.json:

    "extra": {
        "laravel": {
            "dont-discover": ["yaroslavpopovic/laravel-policy-soft-cache"]
        }
    }
  3. Run composer install so the change takes effect.

Testing

composer test

Credits

  • Tim Geisendörfer — original author of innoge/laravel-policy-soft-cache. All the package architecture, the SoftCacheable interface, and the Gate::before hook strategy are his work.
  • Yaroslav Popovic — fork maintainer, swapped the cache-key strategy to spl_object_id for high-throughput rendering use cases.
  • Upstream contributors

License

MIT. See LICENSE.md.