imagina/laravel-responsecache

通过缓存整个响应来加速Laravel应用程序


README

Social Card of Laravel Response Cache

通过缓存整个响应来加速应用程序

Latest Version on Packagist MIT Licensed Psalm Total Downloads

这个Laravel包可以缓存整个响应。默认情况下,它将缓存所有成功返回基于文本内容(如html和json)的get请求一周。这可能会显著加快响应速度。

因此,第一次请求进来时,包会将响应保存起来再发送给用户。当相同的请求再次进来时,我们不会通过整个应用程序,而是直接使用保存的响应进行响应。

你是视觉学习者吗?那么请观看这个视频,它涵盖了如何使用laravel-responsecache以及它是如何工作的。

支持我们

我们投入了大量资源来创建最佳开源包。您可以通过购买我们的付费产品之一来支持我们。

我们非常感激您从您的家乡寄来明信片,并提到您正在使用我们的哪个包。您可以在我们的联系页面上找到我们的地址。我们在我们的虚拟明信片墙上发布了所有收到的明信片。

安装

您可以通过composer安装此包

composer require spatie/laravel-responsecache

该包将自动注册自己。

您可以使用以下命令发布配置文件

php artisan vendor:publish --provider="Spatie\ResponseCache\ResponseCacheServiceProvider"

这是发布配置文件的内容

// config/responsecache.php

return [
    /*
     * Determine if the response cache middleware should be enabled.
     */
    'enabled' => env('RESPONSE_CACHE_ENABLED', true),

    /*
     *  The given class will determinate if a request should be cached. The
     *  default class will cache all successful GET-requests.
     *
     *  You can provide your own class given that it implements the
     *  CacheProfile interface.
     */
    'cache_profile' => Spatie\ResponseCache\CacheProfiles\CacheAllSuccessfulGetRequests::class,

    /*
     * When using the default CacheRequestFilter this setting controls the
     * default number of seconds responses must be cached.
     */
    'cache_lifetime_in_seconds' => env('RESPONSE_CACHE_LIFETIME', 60 * 60 * 24 * 7),

    /*
     * This setting determines if a http header named with the cache time
     * should be added to a cached response. This can be handy when
     * debugging.
     */
    'add_cache_time_header' => env('APP_DEBUG', true),

    /*
     * This setting determines the name of the http header that contains
     * the time at which the response was cached
     */
    'cache_time_header_name' => env('RESPONSE_CACHE_HEADER_NAME', 'laravel-responsecache'),

    /*
     * Here you may define the cache store that should be used to store
     * requests. This can be the name of any store that is
     * configured in app/config/cache.php
     */
    'cache_store' => env('RESPONSE_CACHE_DRIVER', 'file'),

    /*
     * Here you may define replacers that dynamically replace content from the response.
     * Each replacer must implement the Replacer interface.
     */
    'replacers' => [
        \Spatie\ResponseCache\Replacers\CsrfTokenReplacer::class,
    ],

    /*
     * If the cache driver you configured supports tags, you may specify a tag name
     * here. All responses will be tagged. When clearing the responsecache only
     * items with that tag will be flushed.
     *
     * You may use a string or an array here.
     */
    'cache_tag' => '',

    /*
     * This class is responsible for generating a hash for a request. This hash
     * is used to look up an cached response.
     */
    'hasher' => \Spatie\ResponseCache\Hasher\DefaultHasher::class,

    /*
     * This class serializes cache data and expands it.
     * Serialization can save the data to be returned in an appropriate form.
     */
    'serializer' => \Spatie\ResponseCache\Serializer\DefaultSerializer::class,
];

最后,您应该在http内核中安装提供的中间件\Spatie\ResponseCache\Middlewares\CacheResponse::class\Spatie\ResponseCache\Middlewares\DoNotCacheResponse

// app/Http/Kernel.php

...

protected $middlewareGroups = [
   'web' => [
       ...
       \Spatie\ResponseCache\Middlewares\CacheResponse::class,
   ],

...

protected $routeMiddleware = [
   ...
   'doNotCacheResponse' => \Spatie\ResponseCache\Middlewares\DoNotCacheResponse::class,
];

用法

基本用法

默认情况下,该包将缓存所有成功的get请求一周。登录用户将各自有自己的缓存。如果这是您需要的行为,您就完成了:安装ResponseCacheServerProvider就足够了。

清除缓存

手动

可以使用以下命令清除整个缓存

ResponseCache::clear();

这将清除在配置文件中指定的缓存存储中的一切。

使用控制台命令

同样可以通过发出此artisan命令来完成

php artisan responsecache:clear

使用模型事件

您可以使用模型事件来清除模型保存或删除时的缓存。以下是一个示例。

namespace App\Traits;

use Spatie\ResponseCache\Facades\ResponseCache;

trait ClearsResponseCache
{
    public static function bootClearsResponseCache()
    {
        self::created(function () {
            ResponseCache::clear();
        });

        self::updated(function () {
            ResponseCache::clear();
        });

        self::deleted(function () {
            ResponseCache::clear();
        });
    }
}

忘记一个或多个特定的URI(s)

您可以使用以下方法忘记特定的URI

// Forget one URI
ResponseCache::forget('/some-uri');

// Forget several URIs
ResponseCache::forget(['/some-uri', '/other-uri']);

// Alternatively
ResponseCache::forget('/some-uri', '/other-uri');

只有当您在缓存配置文件中没有使用cacheNameSuffix时,forget方法才有效。

防止请求被缓存

可以使用doNotCacheResponse中间件忽略请求。此中间件可以分配给路由和控制器

使用中间件的路由可以免于缓存。

// app/Http/routes.php

Route::get('/auth/logout', ['middleware' => 'doNotCacheResponse', 'uses' => 'AuthController@getLogout']);

或者,您可以将中间件添加到控制器中

class UserController extends Controller
{
    public function __construct()
    {
        $this->middleware('doNotCacheResponse', ['only' => ['fooAction', 'barAction']]);
    }
}

创建自定义缓存配置文件

为了确定哪些请求应该被缓存以及缓存多长时间,使用缓存配置文件类。处理这些问题的默认类是Spatie\ResponseCache\CacheProfiles\CacheAllSuccessfulGetRequests

您可以通过实现 Spatie\ResponseCache\CacheProfiles\CacheProfile接口来创建自己的缓存配置文件类。让我们看看这个接口

interface CacheProfile
{
    /*
     * Determine if the response cache middleware should be enabled.
     */
    public function enabled(Request $request): bool;

    /*
     * Determine if the given request should be cached.
     */
    public function shouldCacheRequest(Request $request): bool;

    /*
     * Determine if the given response should be cached.
     */
    public function shouldCacheResponse(Response $response): bool;

    /*
     * Return the time when the cache must be invalidated.
     */
    public function cacheRequestUntil(Request $request): DateTime;

    /**
     * Return a string to differentiate this request from others.
     *
     * For example: if you want a different cache per user you could return the id of
     * the logged in user.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return mixed
     */
    public function useCacheNameSuffix(Request $request);
}

缓存特定路由

您可以选择将 cacheResponse 中间件注册为路由中间件,而不仅仅是全局注册。

protected $routeMiddleware = [
   ...
   'cacheResponse' => \Spatie\ResponseCache\Middlewares\CacheResponse::class,
];

当使用路由中间件时,您可以指定这些路由应缓存多少秒。

// cache this route for 5 minutes
Route::get('/my-special-snowflake', 'SnowflakeController@index')->middleware('cacheResponse:300');

// cache all these routes for 10 minutes
Route::group(function() {
   Route::get('/another-special-snowflake', 'AnotherSnowflakeController@index');

   Route::get('/yet-another-special-snowflake', 'YetAnotherSnowflakeController@index');
})->middleware('cacheResponse:600');

使用标签

如果您配置的缓存驱动程序支持标签,您可以在应用中间件时指定一个标签列表。[链接](https://laravel.net.cn/docs/5.8/cache#cache-tags "cache tags")

// add a "foo" tag to this route with a 300 second lifetime
Route::get('/test1', 'SnowflakeController@index')->middleware('cacheResponse:300,foo');

// add a "bar" tag to this route
Route::get('/test2', 'SnowflakeController@index')->middleware('cacheResponse:bar');

// add both "foo" and "bar" tags to these routes
Route::group(function() {
   Route::get('/test3', 'AnotherSnowflakeController@index');

   Route::get('/test4', 'YetAnotherSnowflakeController@index');
})->middleware('cacheResponse:foo,bar');

清除标签内容

您可以清除被分配了标签或标签列表的响应。例如,此语句将删除上面的 '/test3''/test4' 路由。

ResponseCache::clear(['foo', 'bar']);

相比之下,此语句将仅删除 '/test2' 路由。

ResponseCache::clear(['bar']);

请注意,这使用了 [Laravel 内置的缓存标签功能](https://laravel.net.cn/docs/master/cache#cache-tags "Laravel's built in cache tags"),这意味着路由也可以以常规方式清除。

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

事件

您可以使用几个事件来监控和调试应用程序中的响应缓存。

ResponseCacheHit

Spatie\ResponseCache\Events\ResponseCacheHit

当请求通过 ResponseCache 中间件并且找到了并返回了缓存响应时,将触发此事件。

CacheMissed

Spatie\ResponseCache\Events\CacheMissed

当请求通过 ResponseCache 中间件但没有找到或返回缓存响应时,将触发此事件。

ClearingResponseCache 和 ClearedResponseCache

Spatie\ResponseCache\Events\ClearingResponseCache

Spatie\ResponseCache\Events\ClearedResponseCache

responsecache:clear 开始和结束时分别触发这些事件。

创建一个 Replacer

要替换缓存内容为动态内容,您可以创建一个替换器。默认情况下,我们在配置文件中添加了一个 CsrfTokenReplacer

您可以通过实现 Spatie\ResponseCache\Replacers\Replacer 接口来创建自己的替换器。让我们看看这个接口。

interface Replacer
{
    /*
     * Transform the initial response before it gets cached.
     *
     * For example: replace a generated csrf_token by '<csrf-token-here>' that you can
     * replace with its dynamic counterpart when the cached response is returned.
     */
    public function transformInitialResponse(Response $response): void;

    /*
     * Replace any data you want in the cached response before it gets
     * sent to the browser.
     *
     * For example: replace '<csrf-token-here>' by a call to csrf_token()
     */
    public function replaceCachedResponse(Response $response): void;
}

之后,您可以在 responsecache.php 配置文件中定义您的替换器。

/*
 * Here you may define replacers that dynamically replace content from the response.
 * Each replacer must implement the Replacer interface.
 */
'replacers' => [
    \Spatie\ResponseCache\Replacers\CsrfTokenReplacer::class,
],

自定义序列化器

序列化器负责将响应序列化以便存储在缓存中。它还负责从缓存中重建响应。

默认序列化器 Spatie\ResponseCache\Serializer\DefaultSerializer 在大多数情况下都能正常工作。

如果您有一些特殊的序列化需求,您可以在配置文件的 serializer 键中指定一个自定义序列化器。任何实现 Spatie\ResponseCache\Serializers\Serializer 的类都可以使用。这是该接口的外观。

namespace Spatie\ResponseCache\Serializers;

use Symfony\Component\HttpFoundation\Response;

interface Serializer
{
    public function serialize(Response $response): string;

    public function unserialize(string $serializedResponse): Response;
}

变更日志

请参阅 [变更日志](https://github.com/imagina/laravel-responsecache/blob/HEAD/CHANGELOG.md "CHANGELOG") 以获取最近更改的更多信息。

测试

您可以使用以下命令运行测试:

composer test

替代方案

  • Barry Vd. Heuvel 开发了一个 [包](https://github.com/barryvdh/laravel-httpcache "laravel-httpcache"),该包通过利用 HttpCache 缓存响应。
  • Joseph Silber 创建了一个 [Laravel Page Cache](https://github.com/JosephSilber/page-cache "Laravel Page Cache"),它可以将缓存写入磁盘,并让 Nginx 读取它们,这样 PHP 就不需要再启动了。

贡献

请参阅 [贡献指南](https://github.com/imagina/laravel-responsecache/blob/HEAD/CONTRIBUTING.md "CONTRIBUTING") 以获取详细信息。

安全

如果您发现任何安全相关的问题,请通过电子邮件 freek@spatie.be 联系,而不是使用问题跟踪器。

致谢

特别感谢 Caneco 为我们设计了标志 ✨

许可

MIT 许可证 (MIT)。请参阅 [许可文件](https://github.com/imagina/laravel-responsecache/blob/HEAD/LICENSE.md "License File") 以获取更多信息。