Azure Redis Cache en Symfony 4

Casi me desespero pero al final he conseguido configurar Azure Redis Cache en Symfony 4, utilizando el componente que viene con el propio framework. Aquí te dejo los pasos por si te desesperas tú también.

Crear proyecto con Symfony 4

Ya sabes, utiliza el comando composer create-project para crear el esqueleto de una aplicación web.

composer create-project symfony/website-skeleton azure-redis-cache-loves-symfony

Instalar predis/predis

A través de composer require instala la librería predis/predis para poder usar el adaptador de Redis. En el momento de escribir este artículo la versión de la misma era la 1.1.

composer require predis/predis

Configura config/services.yaml

Este es el archivo services.yaml por defecto más los valores necesarios para cache con Redis:

#config/services.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: 'en'
redis.host: '%env(REDIS_HOST)%'
redis.port: '%env(REDIS_PORT)%'
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
cache.app:
class: Symfony\Component\Cache\Adapter\ChainAdapter
arguments:
$adapters: ['@app.cache.redis']
view raw services.yaml hosted with ❤ by GitHub

Configurar config/packages/cache.yaml

En todos los artículos e hilos de StackOverflow que me he recorrido, no encontré ninguno que hablara del archivo cache.yaml. Ahora ya aparece por defecto con el esqueleto que he utilizado para este ejemplo:

framework:
cache:
# Put the unique name of your app here: the prefix seed
# is used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The app cache caches to the filesystem by default.
# Other options include:
# Redis
app: cache.adapter.redis
default_redis_provider: redis://%redis.host%:%redis.port%
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu
# Namespaced pools use the above "app" backend by default
#pools:
#my.dedicated.cache: ~
pools:
app.cache.redis:
adapter: cache.adapter.redis
default_lifetime: 86400
view raw cache.yaml hosted with ❤ by GitHub

Por supuesto, en tu archivo .env necesitas los valores para REDIS_HOST y REDIS_PORT. En el caso de REDIS_HOST (6379) he utilizado el siguiente formato:

[email protected]_AZURE_REDIS_NAME.redis.cache.windows.net

Úsalo

Ahora falta comprobar que todo funciona correctamente. Crea un controlador de prueba con el siguiente contenido:

<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Routing\Annotation\Route;
class HomeController extends AbstractController
{
private $cache;
public function __construct(AdapterInterface $cacheClient)
{
$this->cache = $cacheClient;
}
/**
* @Route("/", name="home")
*/
public function index()
{
$itemCache = $this->cache->getItem('cached');
$cached = 'no';
if (!$itemCache->isHit()) {
$itemCache->set('yes');
$this->cache->save($itemCache);
} else {
$cached = $itemCache->get();
}
return $this->render('home/index.html.twig', [
'controller_name' => 'HomeController',
'cached' => $cached,
]);
}
}
view raw HomeController.php hosted with ❤ by GitHub

Además, he modificado un poco la página home/index.html.twig para que muestre el valor de cached.

{% extends 'base.html.twig' %}
{% block title %}Hello HomeController!{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
<h1>Cached: {{cached}}</h1>
</div>
{% endblock %}
view raw index.html.twig hosted with ❤ by GitHub

La primera vez debería de aparecer el valor de Cached: no, al no tener el valor de la variable en Azure Redis Cache. Sin embargo, una vez se ha realizado la primera petición a tu página, si vuelves a cargarla esta aparecerá con el valor almacenado ya en cache, que es yes 🙂

Azure Redis Cache and Symfony 4
Azure Redis Cache and Symfony 4

El código lo tienes en mi GitHub.

¡Saludos!