├── CHANGELOG.md ├── README.md ├── composer.json ├── phpunit.xml └── src ├── GateCache.php └── GateCacheProvider.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [3.9.0] - 2025-03-04 8 | ### Added 9 | - Support Laravel 12.x 10 | 11 | ## [3.8.0] - 2024-03-12 12 | ### Added 13 | - Support Laravel 11.x 14 | 15 | ## Removed 16 | - Support for Laravel 8.x 17 | - Support for Laravel 9.x 18 | 19 | ## [3.7.0] - 2023-11-30 20 | ### Added 21 | - Support for PHP 8.3 22 | 23 | ## Removed 24 | - Support for PHP 8.0 25 | 26 | ## [3.6.0] - 2023-03-07 27 | ### Added 28 | - Support Laravel 10.x 29 | 30 | ## Removed 31 | - Support for Laravel 8.x 32 | - Support for PHP 7.x 33 | 34 | ## [3.5.0] - 2022-10-11 35 | ### Removed 36 | - Support for Laravel 5.5-7.x 37 | - Support for PHP 7.1-7.3 38 | 39 | ## [3.4.0] - 2022-03-01 40 | ### Added 41 | - Support for Laravel 9.x 42 | - Support for PHP 8.1 43 | 44 | ## [3.3.0] - 2021-04-02 45 | ### Added 46 | - Support for Laravel 8.x 47 | 48 | ## [3.2.0] - 2020-12-21 49 | ### Added 50 | - Support for PHP 8.0 51 | 52 | ## [3.1.0] - 2020-04-08 53 | ### Added 54 | - Support for Laravel 7.x 55 | 56 | ## [3.0.1] - 2019-10-14 57 | ### Fixed 58 | - Fixed CI suite for Laravel 6.x 59 | 60 | ## [3.0.0] - 2019-10-12 61 | ### Added 62 | - Support for Laravel 6.x 63 | 64 | ## [2.0.0] - 2019-05-23 65 | ### Added 66 | - Support for Laravel 5.8 67 | 68 | ## [1.1.0] - 2018-10-16 69 | ### Added 70 | - Cache calls to `forUser` 71 | 72 | ## [1.0.0] - 2018-10-10 73 | ### Added 74 | - `GateCache` to cache gate checks for each request 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Laravel Gate Cache 2 | ================== 3 | 4 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE) 5 | ![Packagist Version](https://img.shields.io/packagist/v/rickselby/laravel-gate-cache) 6 | 7 | Add a per-request caching layer to Laravel's Gate. 8 | 9 | | Laravel Auto Presenter Mapper | Laravel | 10 | |-------------------------------|----------| 11 | | **3.x** | 5.5-11.x | 12 | | 2.x | 5.5-5.8 | 13 | | 1.x | 5.5-5.7 | 14 | 15 | ## Installing 16 | 17 | Require the project using [Composer](https://getcomposer.org): 18 | 19 | ```bash 20 | $ composer require rickselby/laravel-gate-cache 21 | ``` 22 | 23 | Laravel will auto-discover the package. 24 | 25 | ## Use Case 26 | 27 | As discussed on [reddit](https://www.reddit.com/r/laravel/comments/9mknx6/) - multiple calls to `Gate` methods 28 | result in the underlying code being re-run. Take this pseudo-blade-code, for example: 29 | 30 | ``` 31 | @foreach($posts as $post) 32 | @can('add_posts') BUTTON @endcan 33 | @can('edit_posts') BUTTON @endcan 34 | @can('delete_posts') BUTTON @endcan 35 | @endforeach 36 | ``` 37 | 38 | Normally, each permission check would be called as many times as there are posts. With this package, 39 | they will only be called once; their results will be cached for any further calls. 40 | 41 | Note that this is per-request only. Each request will test each permission once... but only once. 42 | 43 | ## License 44 | 45 | Laravel Form Components is licensed under [The MIT License (MIT)](LICENSE). 46 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rickselby/laravel-gate-cache", 3 | "description": "Add a per-request caching layer to Laravel's Gate", 4 | "minimum-stability": "stable", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Rick Selby", 9 | "email": "rick@selby-family.co.uk" 10 | } 11 | ], 12 | "require": { 13 | "illuminate/auth": "^10.0|^11.0|^12.0", 14 | "illuminate/contracts": "^10.0|^11.0|^12.0" 15 | }, 16 | "require-dev": { 17 | "graham-campbell/testbench": "^6.1", 18 | "phpunit/phpunit": "^10.0|^11.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "RickSelby\\Laravel\\GateCache\\": "src/" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "RickSelby\\Tests\\": "tests/" 28 | } 29 | }, 30 | "config": { 31 | "allow-plugins": { 32 | "kylekatarnls/update-helper": false 33 | } 34 | }, 35 | "extra": { 36 | "laravel": { 37 | "providers": [ 38 | "RickSelby\\Laravel\\GateCache\\GateCacheProvider" 39 | ] 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests 6 | 7 | 8 | 9 | 10 | ./src 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/GateCache.php: -------------------------------------------------------------------------------- 1 | rawResults = collect(); 28 | } 29 | 30 | /** 31 | * Get the cached raw result from the authorization callback. 32 | * 33 | * @param string $ability 34 | * @param array|mixed $arguments 35 | * @return mixed 36 | */ 37 | public function raw($ability, $arguments = []) 38 | { 39 | $hash = $this->getHash($ability, $arguments); 40 | 41 | if (! $this->rawResults->has($hash)) { 42 | $this->rawResults->put($hash, parent::raw($ability, $arguments)); 43 | } 44 | 45 | return $this->rawResults->get($hash); 46 | } 47 | 48 | /** 49 | * Cache each instance of Gate per user... 50 | * 51 | * @param \Illuminate\Contracts\Auth\Authenticatable|mixed $user 52 | * @return Gate|GateContract|mixed 53 | */ 54 | public function forUser($user) 55 | { 56 | if (! isset($this->userInstances[$user->getAuthIdentifier()])) { 57 | $this->userInstances[$user->getAuthIdentifier()] = parent::forUser($user); 58 | } 59 | 60 | return $this->userInstances[$user->getAuthIdentifier()]; 61 | } 62 | 63 | /** 64 | * Generate a unique hash for the request. 65 | * 66 | * @param $ability 67 | * @param $arguments 68 | * @return string 69 | */ 70 | protected function getHash($ability, $arguments) 71 | { 72 | return hash('md5', $ability.json_encode($arguments)); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/GateCacheProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton(GateContract::class, function ($app) { 14 | return new GateCache($app, function () use ($app) { 15 | return call_user_func($app['auth']->userResolver()); 16 | }); 17 | }); 18 | } 19 | } 20 | --------------------------------------------------------------------------------