anosim/matryoshka

Laravel 的俄罗斯套娃缓存。

1.0.0 2016-04-15 14:15 UTC

This package is not auto-updated.

Last update: 2024-09-26 01:25:26 UTC


README

Matryoshka 是一个为 Laravel 提供俄罗斯套娃缓存的包。

想了解这个包是如何从头开始制作的吗?请访问 Laracasts.com

安装

步骤 1:Composer

在命令行中运行

composer require laracasts/matryoshka

步骤 2:服务提供者

对于您的 Laravel 应用,打开 config/app.php 并在 providers 数组中追加

Laracasts\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

通过将此 HTML 块包围在 @cache@endcache 指令之间,我们要求包缓存给定的 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

在这个例子中,我们将 $post 对象本身传递给 @cache 指令,而不是一个字符串。然后,包将在模型上查找 getCacheKey() 方法。我们已为您完成了这项工作;只需让您的 Eloquent 模型使用 Laracasts\Matryoshka\Cacheable 特性,如下所示

use Laracasts\Matryoshka\Cacheable;

class Post extends Eloquent
{
    use Cacheable;
}

或者,您可以在您 Eloquent 模型继承的父类上使用此特性。

这就完成了!现在,此片段的缓存键将包括对象的 idupdated_at 时间戳:App\Post/1-13241235123

关键是,因为我们把 updated_at 时间戳纳入缓存键,所以每次更新给定的帖子时,缓存键都会更改。这将有效地使缓存失效!

触碰

为了使这种技术正常工作,我们有一个机制来提醒父级关系(随后使父级缓存失效)每次模型被更新时至关重要。以下是一个基本的工作流程

  1. 模型在数据库中被更新。
  2. updated_at 时间戳被刷新,触发了实例的新缓存键。
  3. 模型“触碰”(或ping)其父级。
  4. 父元素的 updated_at 时间戳也会更新,这将清除其相关的缓存。
  5. 只有受影响的片段会重新渲染。所有其他缓存项保持不变。

幸运的是,Laravel 默认提供了这个“touch”功能。考虑一个需要每次更新时都提醒其父 Card 关系的 Note 对象。

<?php

namespace App;

use Laracasts\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 在笔记更新时调用 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 部分就永远不会运行。相反,像往常一样,我们会从缓存中获取。

在幕后,这个包会检测到您将 Laravel 集合传递给了 cache 指令,随后将为集合生成一个唯一的缓存键。

常见问题解答(FAQ)

1. 有没有方法可以覆盖模型实例的缓存键?

是的。假设您有

@cache($post)
    <div>view here</div>
@endcache

在幕后,我们会查找模型上的 getCacheKey 方法。现在,如前所述,您可以使用 Laracasts\Matryoshka\Cacheable 特性立即导入此功能。或者,您也可以向 @cache 指令传递第二个参数,如下所示

@cache($post, 'my-custom-key')
    <div>view here</div>
@endcache

这会指示该包使用 my-custom-key 作为缓存键。这对于分页和其他相关任务非常有用。

2. 我在哪里可以了解更多关于这种缓存方法的细节?

请阅读这两篇文章

如果您喜欢 Laracasts,您可以在这里观看从零开始创建此包的过程。