laragear/cache-query

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

资助包维护!
Github 赞助
Paypal

安装数: 35 060

依赖项: 0

建议者: 0

安全性: 0

星标: 249

关注者: 1

分支: 16

v4.0.0 2024-03-04 04:27 UTC

README

Latest Version on Packagist Latest stable test run Codecov coverage Maintainability Sonarcloud Status Laravel Octane Compatibility

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

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

成为赞助商

您的支持使我能够保持此包免费、最新和维护。或者,您也可以 传播这个词!

要求

  • Laravel 10 或更高版本

安装

您可以通过 composer 安装此包

composer require laragear/cache-query

使用

只需使用 cache() 方法来记住查询结果,默认为 60 秒。

use Illuminate\Support\Facades\DB;
use App\Models\Article;

DB::table('articles')->latest('published_at')->take(10)->cache()->get();

Article::latest('published_at')->take(10)->cache()->get();

下次您调用 相同的 查询时,结果将从缓存中检索,而不是在数据库中运行 SELECT SQL 语句,即使结果为空、nullfalse

它是 预加载感知 的。这意味着它会自动缓存预加载的关系。

use App\Models\User;

$usersWithPosts = User::where('is_author')->with('posts')->cache()->paginate();

生存时间

默认情况下,查询的结果将被缓存 60 秒,当您的应用程序被相同的查询结果猛烈打击时,这通常足够了。

您现在可以使用任意数量的秒数,或只是一个 Carbon 实例。

use Illuminate\Support\Facades\DB;
use App\Models\Article;

DB::table('articles')->latest('published_at')->take(10)->cache(120)->get();

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

您还可以使用 null 来设置查询结果永久。

use App\Models\Article;

Article::latest('published_at')->take(10)->cache(null)->get();

有时您可能需要程序性地重新生成结果。为此,将时间设置为 false。这将用新的结果重新填充缓存,即使这些结果之前没有被缓存。

use App\Models\Article;

$regen = request()->isNotFilled('no-cache');

Article::latest('published_at')->take(10)->cache($regen)->get();

最后,您可以使用查询构建器的 when()unless() 方法轻松绕过缓存,因为这些方法与 cache() 方法完全兼容。

use App\Models\Article;

Article::latest('published_at')->whereBelongsTo($user)->take(10)->unless(Auth::check(), function ($articles) {
    // If the user is a guest, use the cache to show the latest articles of the given user.
    $articles->cache();
})->get();

自定义缓存存储

您可以通过设置第三个参数或一个命名参数,使用任何与应用程序默认值不同的缓存存储。

use App\Models\Article;

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

缓存锁(数据竞争)

在多个进程上,查询可能会多次执行,直到第一个进程能够将结果存储到缓存中,特别是在这些操作需要超过一秒钟时。例如,1,000 个用户同时读取网站的最新 10 篇帖子将会调用数据库 100 次。

为了避免这种情况,设置 wait 参数为获取锁要持有的秒数。

use App\Models\Article;

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

第一个进程将获取给定秒数的锁并执行查询。下一个进程将等待相同数量的秒数,直到第一个进程将结果存储到缓存中以便检索。如果第一个进程花费时间太多,第二个进程将再次尝试。

如果您需要一个更高级的锁定机制,请直接使用 缓存锁

使用键忘记结果

缓存键用于识别具有可识别名称的多个缓存的查询。这不是强制的,但如果您希望从缓存中删除查询,您将需要使用 key 参数来识别查询。

use App\Models\Article;

Article::latest('published_at')->with('drafts')->take(5)->cache(key: 'latest_articles')->get();

完成之后,您可以使用 CacheQuery 门面删除查询结果。

use Laragear\CacheQuery\Facades\CacheQuery;

CacheQuery::forget('latest_articles');

或者,您可以使用 CLI 中的 cache-query:forget 命令与键的名称。

php artisan cache-query:forget latest_articles

# Successfully removed [latest_articles] from the [file] cache store. 

您可以使用相同的键为多个查询分组,稍后可以一次性删除。

use App\Models\Article;
use App\Models\Post;
use Laragear\CacheQuery\Facades\CacheQuery;

Article::latest('published_at')->with('drafts')->take(5)->cache(key: 'latest_articles')->get();
Post::latest('posted_at')->take(10)->cache(key: 'latest_articles')->get();

CacheQuery::forget('latest_articles');

此功能不使用缓存标签,因此它将在您设置的任何缓存存储上工作,甚至包括file驱动程序!

配置

要进一步配置该包,发布配置文件

php artisan vendor:publish --provider="Laragear\CacheQuery\CacheQueryServiceProvider" --tag="config"

您将收到包含以下内容的config/cache-query.php配置文件

<?php

return [
    'store' => env('CACHE_QUERY_STORE'),
    'prefix' => 'cache-query',
];

缓存存储

return  [
    'store' => env('CACHE_QUERY_STORE'),
];

默认缓存存储用于存放查询结果。当查询中没有指定时,将使用此设置。如果为空或null,则使用应用程序的默认缓存存储。

您可以通过您的.env文件轻松更改此设置

CACHE_QUERY_STORE=redis

前缀

return  [
    'prefix' => 'cache-query',
];

当存储查询哈希和查询命名键时,将追加此前缀,以避免与其他缓存键冲突。如果与其他键冲突,您可以更改它。

注意事项

此缓存包会做一些聪明的操作,始终以透明的方式从缓存中检索数据,或使用单一方法填充数据,但这个世界远非完美。

操作具有交换性

更改构建器方法的顺序将改变自动生成的缓存键。即使两个或多个查询在视觉上是相同的,语句的顺序也会使哈希完全不同。

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

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

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

为了避免这种情况,请确保始终执行相同的查询,或在应用程序的某个地方(如使用查询作用域)集中查询。

注意 这是有意为之。查询绑定的顺序会使得操作具有交换性,但也会破坏查询索引优化。请将其视为一个特性,而不是一个错误。

无法删除自动生成的键

所有查询都使用连接名称、SQL查询及其绑定值的BASE64编码的MD5哈希进行缓存。这避免了与其他查询(甚至来自不同数据库的查询)的任何冲突,并由于更短的缓存键而使缓存查找更快。

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

这使得从缓存中删除键变得极其困难。如果您需要使缓存失效或重新生成缓存结果,请使用自定义键

PhpStorm占位符

对于PhpStorm用户,有一个用于此包的宏自动完成的占位符文件。您可以使用phpstorm标签发布它们

php artisan vendor:publish --provider="Laragear\CacheQuery\CacheQueryServiceProvider" --tag="phpstorm"

该文件将发布到您项目的.stubs文件夹中。您应将PhpStorm指向这些占位符。

它是如何工作的?

当您使用cache()时,它将连接包装到一个代理对象中。它代理所有方法调用,除了select()selectOne()

一旦通过上述方法执行了SELECT语句,它将检查结果是否在缓存中,然后再执行查询。在缓存命中时,它将返回缓存结果;否则,它将继续执行,使用缓存配置保存结果,并返回它们。

Laravel Octane 兼容性

  • 没有使用过时应用程序实例的单例。
  • 没有使用过时配置实例的单例。
  • 没有使用过时请求实例的单例。
  • 请求期间没有写入静态属性。

使用此包与Laravel Octane不应有任何问题。

升级

安全性

如果您发现任何安全问题,请通过darkghosthunter@gmail.com发送电子邮件,而不是使用问题跟踪器。

许可证

此特定包版本在发布时受MIT许可证的条款约束。

LaravelTaylor Otwell 的商标。版权所有 © 2011-2024 Laravel LLC。