Cómo crear un nuevo filtro de Twig

symfony_1_1.jpg
Solucionex
13
Sep 19

El gestor de plantillas usado por Symfony, Twig, utiliza filtros para poder añadir algo de lógica a las variables que usamos en su entorno, el listado completo está en la documentación oficial: https://twig.symfony.com/doc/2.x/filters/index.html

Las buenas prácticas mandan no añadir lógica a las plantillas de twig, además, el mero hecho de hacer un bucle con un contador es bastante poco legible con codificación twig. Es por esto que están estos filtros: para dar formato a una fecha o un número, escapar cadenas, hacer un join en un array...

Estos filtros han ido creciendo a medida que se han ido creando nuevas versiones, de hecho, los tres últimos son tres funciones para trabajar con arrays que ya están en varios lenguajes: filter, map y reduce. Que se corresponden con las tres funciones del mismo nombre de PHP.

El problema de los filtros es que tenemos un número limitado, luego si queremos añadir lógica a twig sin ensuciar el código lo normal es que escribamos nuestro propio filtro, esto es bastante sencillo, para ello necesitaremos implementar una extensión de Twig:

Añadir el paquete twig/extensions

Si está aún en nuestro composer.json, necesitamos el paquete twig/extensions

$ composer require twig/extensions

Crear la Extensión

En el fichero src/Twig/AppExtension.php será donde escribiremos nuestro código en php.

Pongamos un ejemplo en el que necesitamos obtener un resumen de las x primeras palabras de un texto. Para ello necesitaremos hacer una función que en php sería muy sencilla, pero que en twig nos puede dar auténticos dolores de cabeza, así que implementaremos un filtro "resumen" al que le pasaremos el número de palabras como parámetro, y este, por defecto, será 50.

namespace App\Twig; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; class AppExtension extends AbstractExtension { public function getFilters() { return [ new TwigFilter('resumen', [$this, 'resumen']), ]; } public function resumen($texto, $numPalabras = 30) { $palabras = explode(' ', strip_tags($texto)); return implode(' ', array_slice($palabras, 0, $numPalabras)) . (($numPalabras >= count($palabras)) ? '' : '...'); } }

Registra el servicio

Esta parte es automática si estás utilizando la configuración de Symfony 4 por defecto. Si no es tu caso en el services.yaml deberías añadir:

services: my_filters.twig_extension: class: App\Twig\AppExtension public: false tags: - { name: twig.extension }

Te recordamos que a la clase creada, AppExtension, se le puede poner un constructor y añadirle dependencias en el caso de que necesitemos acceder a algún servicio como el entity manager para obtener algún objeto de la base de datos, o cualquier otro.

Uso del filtro

Ahora usar nuestro filtro será así de fácil:

<div class="noticia"> <div class="imagen-noticia"><img src="{{ noticia.imagen.path }}" /></div> <div class="resumen-noticia">{{ noticia.texto|resumen(100) }} </div> </div>

La documentación Oficial

Te recordamos que la documentación oficial de Symfony es bastante completa, si necesitas completar este post, siempre puedes recurrir a ella: https://symfony.com/doc/current/templating/twig_extension.html.