enlight/stash-view

Stash view 是一个用于 Laravel 的 composer 包,它使用俄罗斯套娃缓存方法来缓存 blade 视图。这极大地提高了网站的速度,并且作为副作用减少了 SQL 查询并解决了 n+1 问题。

资助包维护!
bhushan

0.0.4 2021-08-15 19:45 UTC

This package is auto-updated.

Last update: 2024-09-16 03:19:06 UTC


README

Stash view 是一个用于 Laravel 的 composer 包,它使用俄罗斯套娃缓存方法来缓存视图。

什么是俄罗斯套娃缓存?这是一种非常著名的缓存策略,将你的视图缓存成小块。它在 Rails 社区中相当有名。如果你对此感兴趣,可以查看这个 链接

简单来说,它将你的视图缓存成块。这篇文章将为你提供更清晰的 想法

Russian Doll Caching PNG

现在关于想法就聊到这里,让我们谈谈如何使用它

您还可以在此 查看示例代码

想要视频解释内部结构?请查看这个 youtube 链接。

安装

步骤 1:Composer

首先,使用以下命令使用此包。

composer require enlight/stash-view

步骤 2:服务提供者(可选)

此包支持自动发现,但如果您使用的是 Laravel 5.4 或以下版本,您需要将 ServiceProvider 添加到 providers 数组中。

对于您的 Laravel 应用程序,打开 config/app.php 并在 providers 数组中添加以下内容:

Enlight\StashView\Providers\StashViewServiceProvider::class

这将启动包到 Laravel。

步骤 3:缓存驱动器

为了使此包正常工作,您必须使用支持标签的 Laravel 缓存驱动器(例如 Cache::tags('foo'))。例如 MemcachedRedis 支持此功能。

检查您的 .env 文件,并确保您的 CACHE_DRIVER 选择满足此要求

CACHE_DRIVER=redis

注意:如果您的应用程序设置为 local 环境,则默认情况下此包将使用 array 缓存驱动器以加快开发过程,这样在开发过程中就不需要反复清除缓存。

如果您需要任何帮助,请查看 Laravel 的缓存配置文档

使用

基础知识

现在,安装了此包后,您可以在视图的任何地方使用提供的 @cache Blade 指令,如下所示

@cache('my-cache-key')
    <div>
        <h1>Hello World</h1>
    </div>
@endcache

通过使用 @cache@endcache 指令包围此 HTML 块,我们要求包缓存给定的 HTML。现在这个例子很 trivial,但是你可以想象一个更复杂的视图,其中包含各种嵌套缓存以及触发额外数据库查询的懒加载关系调用。在首次加载并缓存 HTML 片段后,随后的刷新将改为从缓存中提取。因此,那些额外的数据库查询将永远不会执行。这个包的真正酷的功能是它减少了你的 SQL 查询并解决了 n+1 问题。

请注意,在生产环境中,这将会永久缓存HTML片段。然而,在本地开发中,我们使用的是array缓存驱动程序,它将缓存存储在内存中并在任务完成后刷新。这样,您可以随意更新视图和模板,无需担心手动清除缓存。

由于您的生产服务器将永久缓存片段,您可能需要在部署流程中添加一个清除相关缓存的步骤。

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模型使用Enlight\StashView\Traits\Cacheable特质,如下所示

use Enlight\StashView\Traits\Cacheable;

class Post extends Eloquent
{
    use Cacheable;
}

或者,您可以在扩展Eloquent模型的父类上使用这个特质。

这就完成了!现在,这个片段的缓存键将包括对象的主键,即大多数情况下的idupdated_at时间戳:App\Post/1-98765432101

关键是,由于我们将updated_at时间戳考虑到了缓存键中,因此每当更新给定的帖子时,缓存键都会改变。这将有效地清除缓存!

触动

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

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

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

<?php

namespace App;

use Enlight\StashView\Traits\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在笔记更新时pingcard关系的时间戳。

现在,一切准备就绪。您可以像这样渲染视图

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

注意我们缓存的俄罗斯套娃式级联;这是关键。如果任何笔记被更新,其单个缓存将被清除——连同其父级——但任何兄弟将保持不变。

缓存集合

这尚不支持,但已列入待办事项列表。感谢任何好的PR。 :)

常见问题解答

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

是的。假设您有

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

在幕后,我们将查找模型上的getCacheKey方法。现在,如上所述,您可以使用Enlight\StashView\Traits\Cacheable特质立即导入此功能。或者,您可以将自己的缓存键传递给@cache指令,如下所示

@cache('post-pagination')
    <div>view here</div>
@endcache

这指示包使用post-pagination作为缓存。这对于分页和其他相关任务非常有用。

这就完成了。谢谢:)

祝您编码愉快。