liamsystems/rememberable-query

记住查询结果只需一行表达式

v3.1.1 2022-02-16 18:38 UTC

README

让 Laravel 4.2 中的 ->remember() 方法在查询中可用,无需丑陋且令人烦恼的功能。

可记住的查询

使用一种方法记住查询结果。是的,只有一种。

Articles::latest('published_at')->take(10)->remember()->get();

要求

  • PHP 8.0
  • Laravel 8.x

安装

您可以通过 composer 安装此包

composer require liamsystems/rememberable-query

用法

只需使用 remember() 方法在执行前记住查询结果。就这样。该方法会自动将结果记住 60 秒。

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 语句,即使结果是 nullfalse

如果您构建了一个查询而不是执行它,remember() 将会抛出错误。

生存时间

默认情况下,查询会被记住 60 秒,但您可以使用任何长度,DatetimeDateInterval 或 Carbon 实例。

DB::table('articles')->latest('published_at')->take(10)->remember(60 * 60)->get();

Article::latest('published_at')->take(10)->remember(now()->addHour())->get();

忘记 & 缓存

如果您需要在任何时候忘记当前缓存并重新缓存,请注意:可能值得在某处设置一个变量来控制此操作。

Article::latest('published_at')->take(10)->remember(60, 1)->get();

$reCache = 0;
if(\Request::has('cache') && \Request::input('cache') == "true") { $reCache = 1; }
Article::latest('published_at')->take(10)->remember(60, $reCache)->get();

自定义缓存存储

在某些情况下,使用应用程序的默认缓存可能比数据库性能更差,或者可能与其他键冲突。您可以通过设置第三个参数或命名参数来使用任何其他缓存存储。

Article::latest('published_at')->take(10)->remember(store: 'redis')->get();

缓存锁(数据竞争)

在多个进程的情况下,查询可能会被多次执行,直到第一个进程能够将结果存储到缓存中,特别是在这些操作需要超过 1 秒的情况下。为了避免这种情况,设置 wait 参数以指定获取锁的秒数。

Article::latest('published_at')->take(200)->remember(wait: 5)->get();

第一个进程将获取给定秒数的锁,执行查询并将结果存储。下一个进程将等待直到缓存数据可用,然后从那里检索结果。

如果您需要在多个进程中使用此功能,请直接使用 缓存锁

幂等查询

记住查询的原因是为了缓存从数据库中检索的数据,但您可以利用这一点来创建 幂等 查询。

例如,您可以确保对于给定的用户 ID,此查询每天只执行一次。

$key = auth()->user()->getAuthIdentifier();

Article::whereKey(54)->remember(now()->addHour(), "query|user:$key")->increment('unique_views');

此查询的后续执行将不会执行,直到缓存过期,因此在上述示例中,我们意外地创建了一个“唯一查看”机制。

操作 交换

更改 Builder 方法的顺序将改变自动生成的缓存键哈希。即使它们在 视觉上 相同,语句的顺序也会使哈希完全不同。

例如,给定两个在应用程序不同部分中的相似查询,这两个查询 不会 共享相同的缓存结果

User::whereName('Joe')->whereAge(20)->remember()->first();
// Cache key: "query|/XreUO1yaZ4BzH2W6LtBSA=="

User::whereAge(20)->whereName('Joe')->remember()->first();
// Cache key: "query|muDJevbVppCsTFcdeZBxsA=="

为了确保在相似的查询中命中相同的缓存,请使用 自定义缓存键。使用它,所有使用相同键的查询将共享相同的缓存结果

User::whereName('Joe')->whereAge(20)->remember(60, 'query|find_joe')->first();
User::whereAge(20)->whereName('Joe')->remember(60, 'query|find_joe')->first();

这将允许您通过直接询问缓存来检索查询之外的数据。

$joe = Cache::get('query|find_joe');

许可

MIT 许可证(MIT)。有关更多信息,请参阅许可证文件