justustheis / matryoshka
Requires
- illuminate/support: ^6.6
Requires (Dev)
- illuminate/cache: ^6.6
- illuminate/database: ~5.4.0|~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.0|^7.0
- phpunit/phpunit: ^8.0
This package is auto-updated.
Last update: 2021-03-25 14:09:07 UTC
README
Matryoshka 是一个 Laravel 插件,提供了视图逻辑的俄罗斯套娃缓存。
该软件包是基于 laracasts/matryoshka 分支的。
安装
步骤 1:Composer
在命令行中运行
composer require justustheis/matryoshka
步骤 2:服务提供者
对于您的 Laravel 应用,打开 config/app.php 文件,并在 providers 数组中追加
JustusTheis\Matryoshka\MatryoshkaServiceProvider::class
这会将软件包引导到 Laravel 中。
步骤 3:缓存驱动器
为了使该软件包正常工作,您必须使用支持标签的 Laravel 缓存驱动器(例如 Cache::tags('foo'))。Memcached 和 Redis 等驱动器支持此功能。
检查您的 .env 文件,并确保您的 CACHE_DRIVER 选择满足此要求
CACHE_DRIVER=memcached
如果您需要任何帮助,请查看 Laravel 的缓存配置文档。
用法
基础知识
现在软件包已安装,您可以在视图中任何地方使用提供的 @cache Blade 指令,如下所示
@cache('my-cache-key')
<div>
<h1>Hello World</h1>
</div>
@endcache
通过使用 @cache 和 @endcache 指令包围这个 HTML 块,我们请求软件包缓存给定的 HTML。现在这个例子很简单,但是你可以想象一个更复杂的视图,其中包括各种嵌套缓存以及触发额外数据库查询的懒加载关系调用。在缓存 HTML 片段后的首次页面加载之后,每次刷新都会从缓存中获取。这样,那些额外的数据库查询将永远不会执行。
请注意,在生产环境中,这将永久缓存 HTML 片段。另一方面,对于本地开发,我们将自动为您在每次刷新页面时清除相关的缓存。这样,您可以随意更新视图和模板,无需担心手动清除缓存。
现在由于您的生产服务器将永久缓存片段,您希望在部署过程中添加一个步骤来清除相关的缓存。
Cache::tags('views')->flush();
缓存模型
虽然您可以随意为缓存键硬编码任何字符串,但俄罗斯套娃缓存的真正威力在于我们使用基于时间戳的方法。
考虑以下片段
@cache($post)
<article>
<h2>{{ $post->title }}></h2>
<p>Written By: {{ $post->author->username }}</p>
<div class="body">{{ $post->body }}</div>
</article>
@endcache
在这个例子中,我们向 @cache 指令传递了 $post 对象本身,而不是字符串。然后,软件包将在模型上查找 getCacheKey() 方法。我们已经为您完成了这项工作;只需让您的 Eloquent 模型使用 JustusTheis\Matryoshka\Cacheable 特性,如下所示
use JustusTheis\Matryoshka\Cacheable; class Post extends Eloquent { use Cacheable; }
或者,您可以在每个 Eloquent 模型扩展的父类上使用此特性。
这样就完成了!现在,这个片段的缓存键将包括对象的 id 和 updated_at 时间戳:App\Post/1-13241235123。
关键在于,因为我们把
updated_at时间戳分解到缓存键中,所以每次更新指定的帖子时,缓存键都会改变。这实际上会清除缓存!
接触
为了使这种技术能够正确工作,我们必须有一种机制,在每次更新模型时提醒父级关系(并随后清除父级缓存)。以下是一个基本的流程
- 模型在数据库中更新。
- 其
updated_at时间戳被刷新,触发实例的新缓存键。 - 模型“接触”(或ping)其父级。
- 父级的
updated_at时间戳也被更新,这会清除其相关缓存。 - 只有受影响的片段会重新渲染。所有其他缓存项保持不变。
幸运的是,Laravel自带了这种“接触”功能。考虑一个需要每次更新时提醒其父级 Card 关系的 Note 对象。
<?php namespace App; use JustusTheis\Matryoshka\Cacheable; use Illuminate\Database\Eloquent\Model; class Note extends Model { use Cacheable; protected $touches = ['card']; public function card() { return $this->belongsTo(Card::class); } }
注意 $touches = ['card'] 这部分。这指示Laravel每次笔记更新时都ping card 关系的戳记。
现在,一切准备就绪。你可以这样渲染视图
resources/views/cards/_card.blade.php
@cache($card)
<article class="Card">
<h2>{{ $card->title }}</h2>
<ul>
@foreach ($card->notes as $note)
@include ('cards/_note')
@endforeach
</ul>
</article>
@endcache
resources/views/cards/_note.blade.php
@cache($note)
<li>{{ $note->body }}</li>
@endcache
注意我们缓存的俄罗斯套娃式级联;这是关键。如果任何笔记被更新,其个人缓存将清除 - 包括其父级 - 但任何兄弟项将保持不变。
缓存集合
你并不总是想要缓存模型实例;你可能会希望缓存Laravel集合!没问题。
@cache($posts)
@foreach ($posts as $post)
@include ('post')
@endforeach
@endcache
只要 $posts 集合的内容没有改变,那个 @foreach 部分就永远不会运行。相反,像往常一样,我们会从缓存中获取。
在幕后,这个包会检测到你向 cache 指令传递了一个Laravel集合,并且随后为集合生成一个唯一的缓存键。
常见问题解答(FAQ)
1. 是否有方法可以覆盖模型实例的缓存键?
是的。假设你有
@cache($post)
<div>view here</div>
@endcache
在幕后,我们会寻找模型上的 getCacheKey 方法。现在,如上所述,你可以使用 JustusTheis\Matryoshka\Cacheable 特性来立即导入这个功能。或者,你也可以向 @cache 指令传递一个第二个参数,如下所示
@cache($post, 'my-custom-key')
<div>view here</div>
@endcache
这指示包使用 my-custom-key 作为缓存,这在分页和其他相关任务中可能很有用。
2. 我在哪里可以了解更多关于这种缓存方法的信息?
阅读这两篇文章
- https://signalvnoise.com/posts/3112-how-basecamp-next-got-to-be-so-damn-fast-without-using-much-client-side-ui
- https://signalvnoise.com/posts/3113-how-key-based-cache-expiration-works
如果你喜欢Laracasts,在这里从头开始观看这个包的创建。