Cache Symfony controller response in Redis or DB

This article shows how to easily cache Symfony controller’s response in Redis or database using small but convenient php library that I found some time ago on BitBucket. As it has been moved to GitHub recently, I decided to tell others about it.

This neat library is called phpsed/cache.


Usage

This library uses simple annotation to enable cache on any controller:

use Phpsed\Cache\Annotation\Cache;
use Symfony\Component\Routing\Annotation\Route;
/**
*
@Route("/", name = "default")
*
@Cache()
*/

public function
index()
{
...

By default this annotation works without any parameters — it is saved until deleted and cache key is made for specific route from all of GET and POST parameters combined. If there are no parameters, key is made just from route.

But it is possible to pass additional parameters to this annotation:

use Phpsed\Cache\Annotation\Cache;
use Symfony\Component\Routing\Annotation\Route;
/**
*
@Route("/{lang}/{id}", name="default", defaults = {"id" = 0, "lang" = "en"})
*
@Cache(
* expires = 3600,
* attributes = {"id"}
* )
*/

public function
index()
{
...

expires parameter adds ttl to it, meaning that in 3600 it will be invalidated.

attributes adds posibility to specify cache to only use specific attributes from GET and POST to be used in making of a key.
Attribute MUST BE IN either GET or POST in order to be used.
If same attribute exist in both GET and POST, GET parameter will be used.
If there are no valid attributes passed, key for route will be made just from route.

If in the example above no attributes were provided, cache would be made for id and lang. Now it’s only based on id which means that you will still get same cached result when you change lang parameter.


Invalidation

In order to forcefully invalidate cache, endpoint using @Cache annotation must be called with additional header:

PS-CACHE: PS-CACHE-DISABLE

This header will tell annotation to drop cache for this endpoint, process controller instead and save cache with new data.


Configuration

composer require phpsed/cache

By default this library is disabled and @Cache annotation won’t cache anything.
To enable this library, you need to enable it via parameter and add valid providers:

phpsed_cache:
enabled: true
providers:
- snc_redis.session
- doctrine.orm.default_entity_manager

enabled parameter enables/disables this library.

providers is a set of clients where it is possible to save cache.
Configured providers must be valid services and if library is enabled, at least one provider must be configured.
For now this library accepts Predis and Doctrine ORM providers.

To save cache in Redis, configured provider must be a Predis client. If you use Snc\RedisBundle than you can pass any configured snc_redis client.

To save cache in database, configured provider must be EntityManager. Cache will be saved in table named “phpsed_cache_items”. If the table doesn’t exist, on write it will be created.

Library chains providers in configured order using Symfony cache ChainAdapter, which means that:

When an item is not found in the first adapter but is found in the next ones, this adapter ensures that the fetched item is saved to all the adapters where it was previously missing.

I have tried this only in Symfony 4 but guessing by required packages of this library, it should support Symfony 3 as well.


P.S. Please check out my own Symfony 4 libraries :)