一个带有blade支持的laravel俄罗斯套娃缓存系统

v3.0 2023-06-22 17:48 UTC

This package is auto-updated.

Last update: 2024-09-22 20:33:06 UTC


README

Maintenance Packagist Packagist Version GitHub issues GitHub

Kaish

此包高度受laracasts/matryoshka 启发,并部分 fork

安装

需求

步骤 1: Composer

从命令行运行

composer require justustheis/kaish

步骤 2: 服务提供者

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

JustusTheis\Kaish\KaishServiceProvider::class

这将引导包进入Laravel。

步骤 3: 缓存驱动器

为了使此包正常工作,您必须使用支持标记的Laravel缓存驱动器(如 Cache::tags('foo'))。Memcached和Redis等驱动程序支持此功能。

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

CACHE_DRIVER=memcached

使用

基础知识

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

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

通过将此HTML块用 @cache@endcache 指令包围,我们请求包缓存给定的HTML。现在这个例子很简单,但您可以想象一个更复杂的视图,它包括各种嵌套缓存以及触发额外数据库查询的懒加载关系调用。在首次加载并缓存HTML片段后,每次刷新都将从缓存中获取。因此,那些额外的数据库查询将永远不会执行。

请注意,在生产环境中,这将无限期地缓存HTML片段。另一方面,在本地开发中,我们将自动为您刷新页面时清除相关的缓存。这样,您可以随意更新视图和模板,而无需手动清除缓存。

现在,因为您的生产服务器将无限期地缓存片段,您需要在您的部署流程中添加一个步骤来清除相关的缓存。

Cache::tags('views')->flush();

缓存模型

虽然您可以为任何字符串硬编码缓存键,但俄罗斯套娃缓存的力量在于我们使用基于时间戳的方法。

考虑以下片段

@cache('my-cache-key', $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模型使用 JustusTheis\Kaish\Kaishable 特性,如下所示

use JustusTheis\Kaish\Kaishable;

class Post extends Eloquent
{
    use Kaishable;
}

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

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

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

触动

为了使此技术正常工作,我们必须有一种机制,每当模型更新时,都会通知父关系(随后清除父缓存)。以下是一个基本的工作流程

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

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

<?php

namespace App;

use JustusTheis\Kaish\Kaishable;
use Illuminate\Database\Eloquent\Model;

class Note extends Model
{
    use Kaishable;

    protected $touches = ['card'];

    public function card()
    {
        return $this->belongsTo(Card::class);
    }
}

注意$touches = ['card']这部分。这告诉Laravel每次笔记更新时都要pingcard关系的时间戳。

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

resources/views/cards/_card.blade.php

@cache('my-cache-key', $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('my-cache-key', $note)
    <li>{{ $note->body }}</li>
@endcache

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

缓存集合

您不一定想缓存模型实例;您可能还希望缓存Laravel集合!没问题。

@cache('my-cache-key', $posts)
    @foreach ($posts as $post)
        @include ('post')
    @endforeach
@endcache

只要$posts集合的内容没有改变,那个@foreach部分就永远不会运行。相反,像往常一样,我们会从缓存中提取。

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