spatie / laravel-responsecache
通过缓存整个响应来加速Laravel应用程序
Requires
- php: ^8.2
- illuminate/cache: ^10.0|^11.0
- illuminate/console: ^10.0|^11.0
- illuminate/container: ^10.0|^11.0
- illuminate/http: ^10.0|^11.0
- illuminate/support: ^10.0|^11.0
- nesbot/carbon: ^2.63|^3.0
- spatie/laravel-package-tools: ^1.9
Requires (Dev)
- laravel/framework: ^10.0|^11.0
- mockery/mockery: ^1.4
- orchestra/testbench: ^8.0|^9.0
- pestphp/pest: ^2.22
- dev-main
- 7.6.0
- 7.5.2
- 7.5.1
- 7.5.0
- 7.4.10
- 7.4.9
- 7.4.8
- 7.4.7
- 7.4.6
- 7.4.5
- 7.4.4
- 7.4.3
- 7.4.2
- 7.4.1
- 7.4.0
- 7.3.1
- 7.3.0
- 7.2.0
- 7.1.0
- 7.0.1
- 7.0.0
- 6.6.9
- 6.6.8
- 6.6.7
- 6.6.5
- 6.6.4
- 6.6.3
- 6.6.2
- 6.6.1
- 6.6.0
- 6.5.0
- 6.4.0
- 6.3.0
- 6.2.1
- 6.2.0
- 6.1.1
- 6.1.0
- 6.0.2
- 6.0.1
- 6.0.0
- v5.x-dev
- 5.0.3
- 5.0.2
- 5.0.1
- 5.0.0
- 4.4.5
- 4.4.4
- 4.4.3
- 4.4.2
- 4.4.1
- 4.4.0
- 4.3.0
- 4.2.1
- 4.2.0
- 4.1.1
- 4.1.0
- 4.0.1
- 4.0.0
- v3.x-dev
- 3.2.0
- 3.1.0
- 3.0.1
- 3.0.0
- v2.x-dev
- 2.0.0
- v1.x-dev
- 1.1.7
- 1.1.6
- 1.1.5
- 1.1.4
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.0
- 0.0.1
- dev-forget-all-users
This package is auto-updated.
Last update: 2024-09-05 10:07:56 UTC
README
通过缓存整个响应来加速应用程序
此Laravel包可以缓存整个响应。默认情况下,它将缓存所有成功返回基于文本内容(如HTML和JSON)的GET请求一周。这可能会显著提高响应速度。
因此,第一次请求时,包将保存响应然后再发送给用户。当相同的请求再次到来时,我们不会通过整个应用程序,而是直接响应已保存的响应。
您是视觉学习者吗?那么请观看这个视频,了解如何使用laravel-responsecache及其内部工作原理。
支持我们
我们投入了大量资源来创建一流的开放源代码包。您可以通过购买我们的付费产品之一来支持我们。
我们非常感激您从您的家乡寄给我们明信片,并说明您正在使用我们哪个包。您可以在我们的联系页面上找到我们的地址。我们将所有收到的明信片发布在我们的虚拟明信片墙上。
安装
如果您使用PHP 7,请安装此包的v6.x版本。
您可以通过composer安装此包
composer require spatie/laravel-responsecache
此包将自动注册自己。
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="responsecache-config"
这是已发布配置文件的内容
// 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, /* * Optionally, you can specify a header that will force a cache bypass. * This can be useful to monitor the performance of your application. */ 'cache_bypass_header' => [ 'name' => env('CACHE_BYPASS_HEADER_NAME', null), 'value' => env('CACHE_BYPASS_HEADER_VALUE', null), ], /* * 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'), /* * This setting determines if a http header named with the cache age * should be added to a cached response. This can be handy when * debugging. * ONLY works when "add_cache_time_header" is also active! */ 'add_cache_age_header' => env('RESPONSE_CACHE_AGE_HEADER', false), /* * This setting determines the name of the http header that contains * the age of cache */ 'cache_age_header_name' => env('RESPONSE_CACHE_AGE_HEADER_NAME', 'laravel-responsecache-age'), /* * 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 is responsible for serializing responses. */ 'serializer' => \Spatie\ResponseCache\Serializers\DefaultSerializer::class, ];
最后,您应该安装提供的中间件 \Spatie\ResponseCache\Middlewares\CacheResponse::class
和 \Spatie\ResponseCache\Middlewares\DoNotCacheResponse
。
对于laravel 11.x及更高版本
将中间件定义添加到引导应用程序。
// bootstrap/app.php ->withMiddleware(function (Middleware $middleware) { ... $middleware->web(append: [ ... \Spatie\ResponseCache\Middlewares\CacheResponse::class, ]); ... $middleware->alias([ ... 'doNotCacheResponse' => \Spatie\ResponseCache\Middlewares\DoNotCacheResponse::class, ]); })
对于laravel 10.x及更早版本
将中间件定义添加到http内核。
// app/Http/Kernel.php ... protected $middlewareGroups = [ 'web' => [ ... \Spatie\ResponseCache\Middlewares\CacheResponse::class, ], ... protected $middlewareAliases = [ ... 'doNotCacheResponse' => \Spatie\ResponseCache\Middlewares\DoNotCacheResponse::class, ];
使用方法
基本使用
默认情况下,此包将缓存所有成功的 GET
请求一周。登录用户将各自拥有自己的独立缓存。如果这是您需要的行为,您就完成了:安装 ResponseCacheServiceProvider
就足够了。
清除缓存
手动
可以使用以下命令清除整个缓存
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
您可以使用以下方法忘记特定的URI
// Forget one ResponseCache::forget('/some-uri'); // Forget several ResponseCache::forget(['/some-uri', '/other-uri']); // Equivalent to the example above ResponseCache::forget('/some-uri', '/other-uri');
当您没有在缓存配置中使用 cacheNameSuffix
时,ResponseCache::forget
方法才有效,使用 ResponseCache::selectCachedItems
来处理 cacheNameSuffix
。
忘记一组缓存项
您可以使用 ResponseCache::selectCachedItems()
来指定应该忘记哪些缓存项。
// forgetting all PUT responses of /some-uri ResponseCache::selectCachedItems()->withPutMethod()->forUrls('/some-uri')->forget(); // forgetting all PUT responses of multiple endpoints ResponseCache::selectCachedItems()->withPutMethod()->forUrls(['/some-uri','/other-uri'])->forget(); // this is equivalent to the example above ResponseCache::selectCachedItems()->withPutMethod()->forUrls('/some-uri','/other-uri')->forget(); // forget /some-uri cached with "100" suffix (by default suffix is user->id or "") ResponseCache::selectCachedItems()->usingSuffix('100')->forUrls('/some-uri')->forget(); // all options combined ResponseCache::selectCachedItems() ->withPutMethod() ->withHeaders(['foo'=>'bar']) ->withCookies(['cookie1' => 'value']) ->withParameters(['param1' => 'value']) ->withRemoteAddress('127.0.0.1') ->usingSuffix('100') ->usingTags('tag1', 'tag2') ->forUrls('/some-uri', '/other-uri') ->forget();
cacheNameSuffix
依赖于您的缓存配置,默认为用户ID或未认证时的空字符串。
防止请求被缓存
可以通过使用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']]); } }
故意绕过缓存
你可以故意并安全地绕过缓存,并确保你始终接收到最新响应。这可能在你想要分析某个端点或需要调试响应时很有用。在任何情况下,你只需要填写CACHE_BYPASS_HEADER_NAME
和CACHE_BYPASS_HEADER_VALUE
环境变量,然后在请求时使用该自定义头。
创建自定义缓存配置文件
为了确定哪些请求应该被缓存以及缓存多长时间,使用一个缓存配置类。处理这些问题的默认类是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 $middlewareAliases = [ ... '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');
使用标签
如果你的缓存驱动程序配置支持标签,你可以在应用中间件时指定一系列标签。
// 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的内置缓存标签功能,这意味着路由也可以像通常一样被清除
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
时分别触发这些事件。
创建一个替换器
为了用动态内容替换缓存的 内容,你可以创建一个替换器。默认情况下,我们在配置文件中添加了CsrfTokenReplacer
。
你可以通过实现Spatie\ResponseCache\Replacers\Replacer
接口来创建自己的替换器。让我们看看这个接口
interface Replacer { /* * Prepare 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 prepareResponseToCache(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 replaceInCachedResponse(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; }
测试
你可以使用以下命令运行测试
composer test
替代方案
- Barry Vd. Heuvel制作了一个包,该包通过利用HttpCache来缓存响应。
- Joseph Silber 创建了 Laravel Page Cache,它可以将其缓存写入磁盘,并让 Nginx 读取,这样 PHP 甚至不再需要启动了。
更新日志
请参阅 更新日志 以获取更多最近更改的信息。
贡献
请参阅 贡献指南 了解详细信息。
安全性
如果您发现有关安全性的错误,请通过邮件发送到 [email protected],而不是使用问题跟踪器。
鸣谢
特别感谢 Caneco 为标志 ✨
许可
MIT 许可协议(MIT)。有关更多信息,请参阅 许可文件。