Here is what we will need:
- Guzzle 6
- The Guzzle cache middleware
- A PSR-6 cache library of your choice. In this example, I will use the Symfony Cache Component.
If you are using Composer, just add the following lines to the "require" section of your composer.json:
"guzzlehttp/guzzle": "~6.2.2", "symfony/Cache": "~3.2", "psr/cache": "~1.0.1", "kevinrob/guzzle-cache-middleware": "~2.0"
Guzzle 6 supports the use of middleware. This means, that the HTTP requests and responses sent and received by Guzzle will get passed through any number of middleware libraries registered in the stack. Every middleware can do anything with the HTTP message as long as it passes it anwards. So what the cache middleware essentially does, is pass responses to the chosen cache library and fetch them back from the cache if the same request is sent again. It's the cache library, that is responsible for where the cache is actually held: neither Guzzle nor the middleware need to care about that.
So, to enable caching, we need to add the cache middleware with an instance of the chosen cache interface to the middleware stack of Guzzle. In our example we are going to use the Symfony Cache Component with the file system adapter.
use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use Kevinrob\GuzzleCache\CacheMiddleware; use Kevinrob\GuzzleCache\Storage\Psr6CacheStorage; use Symfony\Component\Cache\Adapter\FilesystemAdapter; // Create a HandlerStack $stack = HandlerStack::create(); // Choose a cache strategy: the PrivateCacheStrategy is good to start with $cache_strategy_class = '\\Kevinrob\\GuzzleCache\\Strategy\\PrivateCacheStrategy'; // Instantiate the cache storage: a PSR-6 file system cache with // a default lifetime of 1 minute (60 seconds). $cache_storage = new Psr6CacheStorage( new FilesystemAdapter('', 0, 'your/path/to/cache/folder') ), 60 ); // Add cache middleware to the top of the stack with `push` $stack->push( new CacheMiddleware( new $cache_strategy_class ( $cache_storage ) ), 'cache' ); // Initialize the client with the handler option $client = new Client(['handler' => $stack]);
There are special headers defined in the HTTP protocol standards to control caching: see RFC 7234. The part important for us is, that the server can tell the client, how long the page may be cached and whether it should be a private or a public cache. The public cache can be shared between multiple applications: In particular, such resources may be cached by proxy servers. Depending on how you want your cache to react to those headers, you can use the following built-in cache strategies in the middleware:
- The PrivateCacheStrategy will cache private and public responses
- The PublicCacheStrategy will only cache responses suitable for a public-cache
- The GreedyCacheStrategy will cache everything - even if the header does not allow any caching at all.
Other cache libraries and storages
There are numerous cache storages with their pros and contras for every use case. Using the cache middleware with the PSR-6 driver, you can easily switch to the cache interface of your choice. Most popular cache libraries like Stash, Doctrine Cache or the Symfony Cache Component, will offer multiple storage adapters. The cache middleware, in turn, has special drivers for some of those libraries apart from the general PSR-6 driver. So you have lot's of possibilities to choose from. Happy caching!