faizanbashir/cacheable

为Laravel提供缓存。

dev-master 2018-04-16 07:33 UTC

This package is not auto-updated.

Last update: 2024-09-29 05:41:56 UTC


README

Cacheable是一个为Laravel提供视图逻辑缓存的包。

安装

步骤1: Composer

从命令行运行

composer require faizanbashir/cacheable

步骤2: 服务提供者

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

Faizanbashir\Cacheable\CacheableServiceProvider::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

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

use Faizanbashir\Cacheable\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提供了这个“触摸”功能。考虑一个需要每次更新时都提醒其父级Card关系的Note对象。

<?php

namespace App;

use Faizanbashir\Cacheable\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卡关系的时间戳。

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

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方法。现在,如上所述,你可以使用Faizanbashir\Cacheable\Cacheable特质立即导入这个功能。或者,你也可以像这样向@cache指令传递第二个参数

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

这告诉包使用my-custom-key作为缓存,这可以用于分页和其他相关任务。

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

阅读这两篇文章