laragear / cache-query
仅使用一种方法记住查询结果。是的,只有一种。
Requires
- php: ^8.1
- illuminate/cache: 10.*|11.*
- illuminate/config: 10.*|11.*
- illuminate/container: 10.*|11.*
- illuminate/contracts: 10.*|11.*
- illuminate/database: 10.*|11.*
- illuminate/support: 10.*|11.*
Requires (Dev)
- orchestra/testbench: 8.*|9.*
README
仅使用一种方法记住查询结果。是的,只有一种。
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 语句,即使结果为空、null
或 false
。
它是 预加载感知 的。这意味着它会自动缓存预加载的关系。
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许可证的条款约束。
Laravel 是 Taylor Otwell 的商标。版权所有 © 2011-2024 Laravel LLC。