eusonlito / query-remember
记住 Laravel 查询构建器或 Eloquent 上的查询结果
Requires
- php: ^8.0
- illuminate/database: 8.*
- illuminate/support: 8.*
Requires (Dev)
- mockery/mockery: ^1.4
- orchestra/testbench: ^6.19
- phpunit/phpunit: ^9.5.8
This package is auto-updated.
Last update: 2022-02-25 10:34:30 UTC
README
已迁移到新的仓库,以更高效的方式管理缓存: https://github.com/eusonlito/laravel-database-cache
Query Remember
基于 https://github.com/DarkGhostHunter/RememberableQuery,但增加了标签,并更专注于 Eloquent。
Articles::latest('published_at')->take(10)->remember()->get();
要求
- PHP 8.0
- Laravel 8.x
安装
您可以通过 composer 安装此包
composer require eusonlito/query-remember php artisan vendor:publish --tag=eusonlito-query-remember
与 DarkGhostHunter/RememberableQuery 的差异
- 使用
config/query-remember.php
配置文件可配置 TTL、驱动和启用。 - 使用全局配置将数据库缓存按标签分组。
- 模型可以使用
getCacheTag
和getCacheTagSuffix
方法自定义模型标签。
用法
只需使用 remember()
方法在执行前记住查询结果。就是这样。该方法会自动将结果记住 60 秒。
如果您使用默认配置,此缓存将存储在 ['database', 'database|articles']
标签中。
use Illuminate\Support\Facades\DB; use App\Models\Article; $database = DB::table('articles')->latest('published_at')->take(10)->remember()->get(); $eloquent = Article::latest('published_at')->take(10)->remember()->get();
下次调用 相同的 查询时,结果将从缓存中检索,而不是在数据库中运行 SQL 语句,即使结果是 null
或 false
。
如果构建了查询而不是执行它,
remember()
将引发错误。
生存时间
默认情况下,查询会记住 60 秒,但您可以使用任何长度,例如 Datetime
、DateInterval
或 Carbon 实例。
DB::table('articles')->latest('published_at')->take(10)->remember(60 * 60)->get(); Article::latest('published_at')->take(10)->remember(now()->addHour())->get();
自定义缓存键
自动生成的缓存键是 SQL 查询及其绑定的 BASE64-MD5 哈希,这避免了与其他查询发生冲突,同时保持了缓存键的简短。
如果您使用默认配置,此缓存将存储在 ['database', 'database|articles']
标签中,键为 latest_articles
。
Article::latest('published_at')->take(10)->remember(30, 'latest_articles')->get();
缓存锁(数据竞争)
在多个进程的情况下,查询可能会在第一个进程能够将结果存储到缓存之前多次执行。为了避免这种情况,请设置 wait
参数以获取锁的时间(秒数)。
Article::latest('published_at')->take(200)->remember(wait: 5)->get();
第一个进程将获取给定秒数的锁,执行查询并将结果存储。下一个进程将等待缓存数据可用,然后从中检索结果。
如果您需要在多个进程中使用它,请直接使用 缓存锁。
幂等查询
记住查询的原因是为了缓存从数据库中检索到的数据,您可以利用这一点来创建幂等查询。
例如,您可以使此查询每天只针对特定的用户ID执行一次。
$key = auth()->user()->getAuthIdentifier(); Article::whereKey(54)->remember(now()->addHour(), 'user:'.$key)->increment('unique_views');
在此查询的后续执行将不会执行,直到缓存过期,因此在上述示例中,我们意外地创建了一个“唯一视图”机制。
操作不是交换律的
更改构建方法的顺序将改变自动生成的缓存键哈希。即使它们在视觉上相同,语句的顺序也会使哈希完全不同。
例如,给定应用不同部分中的两个类似查询,这两个查询将不会共享相同的缓存结果
User::whereName('Joe')->whereAge(20)->remember()->first(); User::whereAge(20)->whereName('Joe')->remember()->first();
为确保您在类似的查询中触达相同的缓存,请使用自定义缓存键。有了这个,所有使用相同键的查询都将共享相同的缓存结果
User::whereName('Joe')->whereAge(20)->remember(60, 'find_joe')->first(); User::whereAge(20)->whereName('Joe')->remember(60, 'find_joe')->first();
这将允许您通过直接询问缓存来检索查询之外的数据。
$joe = Cache::tags(['database', 'database|users'])->get('find_joe');
请记住,您需要传递与缓存存储时相同的有序标签列表到tags
方法。当XXX
是查询相关的表名时,始终使用['database', 'database|XXX']
。
标签
此包使用两个不同的标签进行缓存(仅由redis
和memcached
支持)
database
是所有数据库缓存的全球标签。database|XXXX
是每个不同表的标签。表名将在模型上的getTable
方法中设置,或在Query Builder
上的from
字符串中。
模型上的自定义标签
模型可以包括两个方法来创建自定义标签
getCacheTag
将缓存标签与全局标签database
以及由此方法返回的字符串相关联。getCacheTagSuffix
将缓存标签与全局标签database
相关联,并将由此方法返回的字符串附加到database|
之后。
清除缓存
您可以清除所有数据库缓存或仅清除与单个表相关的缓存
// Flush all database cache Cache::tags('database')->flush(); // Flush only users table cache Cache::tags('database|users')->flush();
许可证
MIT许可证(MIT)。请参阅许可证文件以获取更多信息。