├── .php-cs-fixer.dist.php ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json └── src ├── CacheHighOrderFunction.php ├── LaravelQueryCacheServiceProvider.php └── Macros └── CacheMacro.php /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in([ 5 | __DIR__ . '/src', 6 | __DIR__ . '/tests', 7 | ]) 8 | ->name('*.php') 9 | ->notName('*.blade.php') 10 | ->ignoreDotFiles(true) 11 | ->ignoreVCS(true); 12 | 13 | return (new PhpCsFixer\Config()) 14 | ->setRules([ 15 | '@PSR12' => true, 16 | 'array_syntax' => ['syntax' => 'short'], 17 | 'ordered_imports' => ['sort_algorithm' => 'alpha'], 18 | 'no_unused_imports' => true, 19 | 'not_operator_with_successor_space' => true, 20 | 'trailing_comma_in_multiline' => true, 21 | 'phpdoc_scalar' => true, 22 | 'unary_operator_spaces' => true, 23 | 'binary_operator_spaces' => true, 24 | 'blank_line_before_statement' => [ 25 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], 26 | ], 27 | 'phpdoc_single_line_var_spacing' => true, 28 | 'phpdoc_var_without_name' => true, 29 | 'class_attributes_separation' => [ 30 | 'elements' => [ 31 | 'method' => 'one', 32 | ], 33 | ], 34 | 'method_argument_space' => [ 35 | 'on_multiline' => 'ensure_fully_multiline', 36 | 'keep_multiple_spaces_after_comma' => true, 37 | ], 38 | 'single_trait_insert_per_statement' => true, 39 | ]) 40 | ->setFinder($finder); 41 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `laravel-query-cache` will be documented in this file. 4 | 5 | ## 1.0.0 - 202X-XX-XX 6 | 7 | - initial release 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Juan Pablo Barreto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Query Cache 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/juampi92/laravel-query-cache.svg?style=flat-square)](https://packagist.org/packages/juampi92/laravel-query-cache) 4 | [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/juampi92/laravel-query-cache/run-tests.yml?branch=master&style=flat-square)](https://github.com/juampi92/laravel-query-cache/actions?query=workflow%3ATests+branch%3Amaster) 5 | [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/juampi92/laravel-query-cache/php-cs-fixer.yml?branch=master&label=code%20style&style=flat-square)](https://github.com/juampi92/laravel-query-cache/actions?query=workflow%3A"Check+%26+fix+styling"+branch%3Amaster) 6 | [![Total Downloads](https://img.shields.io/packagist/dt/juampi92/laravel-query-cache.svg?style=flat-square)](https://packagist.org/packages/juampi92/laravel-query-cache) 7 | 8 | This package provides a set of macros to cache your Laravel Queries just like Cache::remember. 9 | 10 | ```php 11 | $featuredPost = Post::published()->orderByMostViews() 12 | ->cacheDay('post:featured') // <- Here 13 | ->first(); 14 | ``` 15 | 16 | ## Installation 17 | 18 | You can install the package via composer: 19 | 20 | ```bash 21 | composer require juampi92/laravel-query-cache 22 | ``` 23 | 24 | That's it! No config or Trait necessary. The package auto-discovery will boot the macros. 25 | 26 | ## Usage 27 | 28 | Instead of doing: 29 | 30 | ```php 31 | Cache::remember('post:count', $ttl, () => Post::published()->count()); 32 | ``` 33 | 34 | You now do: 35 | 36 | ```php 37 | Post::published()->cache('post:count', $ttl)->count(); 38 | ``` 39 | 40 | You can use it in Eloquent Queries as well as in normal Queries. 41 | 42 | ```php 43 | DB::table('posts') 44 | ->whereNotNull('published_at') 45 | ->latest() 46 | ->cacheHour('post:latest') 47 | ->first(); 48 | 49 | Posts::published() 50 | ->cacheHour('post:count') 51 | ->count(); 52 | ``` 53 | 54 | List of macros: 55 | 56 | ```php 57 | Post::cache('cache:key', $ttl)->get(); 58 | Post::cacheMinute('cache:key')->first(); 59 | Post::cacheHour('cache:key')->pluck('id'); 60 | Post::cacheDay("cache:key:$id")->find($id); 61 | Post::cacheWeek('cache:key:paginate:10')->paginate(10); 62 | Post::cacheForever('cache:key')->count(); 63 | ``` 64 | 65 | ## Advanced usage 66 | 67 | ### Different store 68 | 69 | ```php 70 | Post::query() 71 | ->where(...) 72 | ->cache('post:count')->store('redis') 73 | ->count(); 74 | ``` 75 | 76 | ### Add your custom cache duration 77 | 78 | This is maybe more advanced, but you can do so by [opting out of discovery](https://laravel.com/docs/8.x/packages#opting-out-of-package-discovery), and then importing it yourself: 79 | 80 | ```php 81 | use Juampi92\LaravelQueryCache\LaravelQueryCacheServiceProvider as BaseServiceProvider; 82 | 83 | class LaravelQueryCacheServiceProvider extends BaseServiceProvider 84 | { 85 | protected function getCustomTimes(): array 86 | { 87 | return array_merge( 88 | parent::getCustomTimes(), 89 | [ 90 | 'rememberForever' => null, 91 | 'cacheFifteenMinutes' => 60 * 15, 92 | ] 93 | ); 94 | } 95 | } 96 | ``` 97 | 98 | The original method has 99 | ```php 100 | [ 101 | 'cacheForever' => null, 102 | 'cacheMinute' => 60, 103 | 'cacheHour' => 60 * 60, 104 | 'cacheDay' => 60 * 60 * 24, 105 | 'cacheWeek' => 60 * 60 * 24 * 7, 106 | ] 107 | ``` 108 | 109 | ## Disclaimer 110 | 111 | This package is supposed to be a nice integration of Cache remember inside the Query Builder. 112 | If you're looking for a advanced eloquent specific cache, I recommend to check out [laravel-eloquent-query-cache](https://github.com/renoki-co/laravel-eloquent-query-cache). 113 | 114 | ## Testing 115 | 116 | ```bash 117 | composer test 118 | ``` 119 | 120 | ## Changelog 121 | 122 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 123 | 124 | ## Contributing 125 | 126 | Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details. 127 | 128 | ## Security Vulnerabilities 129 | 130 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 131 | 132 | ## Credits 133 | 134 | - [Juampi92](https://github.com/juampi92) 135 | - [All Contributors](../../contributors) 136 | 137 | ## License 138 | 139 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 140 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "juampi92/laravel-query-cache", 3 | "description": "Provide easy interface for caching laravel queries", 4 | "keywords": ["laravel", "cache", "query", "queries", "remember"], 5 | "homepage": "https://github.com/juampi92/laravel-query-cache", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Juan Pablo Barreto", 10 | "email": "juampi92@gmail.com" 11 | } 12 | ], 13 | "require": { 14 | "php": ">=7.4", 15 | "illuminate/cache": "^8.0|^9.0|^10.0", 16 | "illuminate/database": "^8.0|^9.0|^10.0", 17 | "illuminate/support": "^8.0|^9.0|^10.0" 18 | }, 19 | "require-dev": { 20 | "friendsofphp/php-cs-fixer": "^3.8", 21 | "mockery/mockery": "^1.4.2", 22 | "orchestra/testbench": "^v7.0", 23 | "phpstan/phpstan": "^1.9", 24 | "phpunit/phpunit": "^9.3" 25 | }, 26 | "autoload": { 27 | "psr-4": { 28 | "Juampi92\\LaravelQueryCache\\": "src" 29 | } 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "Juampi92\\LaravelQueryCache\\Tests\\": "tests" 34 | } 35 | }, 36 | "scripts": { 37 | "test": "vendor/bin/phpunit --colors=always", 38 | "test-coverage": "vendor/bin/phpunit --coverage-html coverage" 39 | }, 40 | "config": { 41 | "sort-packages": true 42 | }, 43 | "extra": { 44 | "laravel": { 45 | "providers": [ 46 | "Juampi92\\LaravelQueryCache\\LaravelQueryCacheServiceProvider" 47 | ], 48 | "aliases": { 49 | "LaravelQueryCache": "Juampi92\\LaravelQueryCache\\LaravelQueryCacheFacade" 50 | } 51 | } 52 | }, 53 | "minimum-stability": "dev", 54 | "prefer-stable": true 55 | } 56 | -------------------------------------------------------------------------------- /src/CacheHighOrderFunction.php: -------------------------------------------------------------------------------- 1 | */ 26 | private array $tags = []; 27 | 28 | /** @var Repository|TaggedCache */ 29 | private $cache; 30 | 31 | /** 32 | * CachedQueryBuilder constructor. 33 | * @param EloquentBuilder|QueryBuilder $query 34 | * @param string $key 35 | * @param \DateTimeInterface|\DateInterval|int|null $ttl 36 | */ 37 | public function __construct($query, string $key, $ttl) 38 | { 39 | $this->query = $query; 40 | $this->key = $key; 41 | $this->ttl = $ttl; 42 | $this->tags = []; 43 | $this->cache = Cache::store(); 44 | } 45 | 46 | public function store(string $name): self 47 | { 48 | $this->cache = Cache::store($name); 49 | 50 | return $this; 51 | } 52 | 53 | /** 54 | * @param array $names 55 | * @return $this 56 | */ 57 | public function tags(array $names): self 58 | { 59 | $this->tags = $names; 60 | 61 | return $this; 62 | } 63 | 64 | public function __call($method, $arguments) 65 | { 66 | if (count($this->tags)) { 67 | $this->cache = $this->cache->tags($this->tags); 68 | } 69 | 70 | if (! $this->ttl) { 71 | return $this->cache->rememberForever( 72 | $this->key, 73 | fn () => $this->callQuery($method, $arguments) 74 | ); 75 | } 76 | 77 | return $this->cache->remember( 78 | $this->key, 79 | $this->ttl, 80 | fn () => $this->callQuery($method, $arguments) 81 | ); 82 | } 83 | 84 | /** 85 | * @param string $method 86 | * @param array $arguments 87 | * @return mixed 88 | */ 89 | private function callQuery($method, $arguments) 90 | { 91 | $result = $this->query->$method(...$arguments); 92 | 93 | if ($result instanceof EloquentBuilder || $result instanceof QueryBuilder) { 94 | throw new RuntimeException('You can\'t cache a query. Remember to use ->cache() right before executing the query.'); 95 | } 96 | 97 | return $result; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/LaravelQueryCacheServiceProvider.php: -------------------------------------------------------------------------------- 1 | registerBaseMacro(); 15 | 16 | foreach ($this->getCustomTimes() as $macroName => $ttl) { 17 | $this->registerCustomMacro($macroName, $ttl); 18 | } 19 | } 20 | 21 | /** 22 | * @return array 23 | */ 24 | protected function getCustomTimes(): array 25 | { 26 | return [ 27 | 'cacheForever' => null, 28 | 'cacheMinute' => 60, 29 | 'cacheHour' => 60 * 60, 30 | 'cacheDay' => 60 * 60 * 24, 31 | 'cacheWeek' => 60 * 60 * 24 * 7, 32 | ]; 33 | } 34 | 35 | private function registerBaseMacro(): void 36 | { 37 | QueryBuilder::macro('cache', call_user_func(new CacheMacro())); 38 | EloquentBuilder::macro('cache', call_user_func(new CacheMacro())); 39 | } 40 | 41 | /** 42 | * Will register every custom 43 | * @param string $macroName 44 | * @param \DateTimeInterface|\DateInterval|int|null $ttl 45 | */ 46 | private function registerCustomMacro(string $macroName, $ttl = null): void 47 | { 48 | QueryBuilder::macro($macroName, CacheMacro::customTTL($ttl)); 49 | EloquentBuilder::macro($macroName, CacheMacro::customTTL($ttl)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Macros/CacheMacro.php: -------------------------------------------------------------------------------- 1 |