Introduciendo shortcodes en Symfony mediante tagged services
Cómo implementar los shortcodes de Wordpress en los campos de texto de las entidades de Symfony

En este artículo quiero enseñaros cómo podemos crear un sistema de shortcodes para vitaminar nuestros campos de texto mediante servicios taggeados, lo cual creo que es un gran ejemplo para introducirse en el mundo de los Compiler Pass y las tags propiamente dichas.
Para los que nunca hayáis trabajado con Wordpress, los shortcodes son una forma sencilla de permitir a los usuarios menos familiarizados con la programación crear elementos complejos como por ejemplo listados de entidades, carruseles o botones.
Para ello, se les provee de ciertos códigos especiales que al escribirlos dentro de los campos de texto serán parseados para mostrar algún elemento más complejo.
Por ejemplo, podemos crearles el siguiente shortcode:
[articles ids="lista de ids"][/articles]
El cual al escribirlo en un campo de texto será transformado automágicamente en una lista de artículos con los ids indicados. Si queréis leer más sobre los shortcodes podéis hacerlo desde aquí:
Dicho esto y como decía al principio del artículo, vamos a usar las tags de los services para crear un sistema que nos permita añadir shortcodes de forma muy sencilla. ¡Vamos a ello!
Procesando shortcodes
Tal y como hace wordpress, lo que queremos es escribir en base de datos un texto con shortcodes y que, en el momento de pintarse, éstos sean procesados y convertidos al HTML correspondiente. Esto nos permitirá volver a editarlos más tarde (realmente también existe la posibilidad de guardar tanto el texto original como el procesado, pero por simplificar el artículo optaremos por esta forma).
Lo primero de todo será implementar un servicio capaz de procesar shortcodes, para lo cual, nos basaremos en el que ya trae wordpress:
De todo ese código, la función que realiza el trabajo es shortcodeProcess
, la cual recibe el texto a procesar y convierte los shortcodes encontrados en el HTML correspondiente. Lo cual está muy bonito siempre y cuando sepamos los shortcodes que tenemos que buscar en el texto.
Es aquí donde entran los tagged services y el Compiler Pass encargado de pasárselos a nuestro servicio recién creado.
Localizando shortcodes en el texto
Si os habéis leido por encima el gist anterior, habréis visto que empleo la función isShortcode
para comprobar si la tag
encontrada es un shortcode reconocido por nuestra aplicación. Es decir, el servicio ShortcodeService
posee un array de shortcodes reconocidos e indexados por nombre, de modo que cuando la función shortcodeProcess
se encuentra con algo del estilo [nombre][/nombre]
trata de ver si nombre
es una clave válida dentro del array shortcodes
.
Este array estará relleno de servicios que implementarán la interfaz ShortcodeInterface
como vamos a ver a continuación.
Creando el Shortcode button
Para ilustrar un poco todo lo comentador anteriormente, vamos a crear primero un shortcode sencillo.
Puesto que todos compartirán los mismos métodos, declararemos primero la interfaz que habrán de implementar.
La interfaz define tres métodos:
getName
, que será en nombre por el cual será indexado en el servicioShortcodeService
getArgs
, que devolverá los argumentosapply
, el cual recibirá como argumentos los atributos y el contenido del shortcode que el usuario haya escrito y devolverá el HTML correspondiente tras haber procesado el shortcode.:
Por tanto, si queremos crear un shortcode que permita al usuario escribir
[button]Esto es un botón[/button]
para generar un botón en HTML:
<button>Esto es un botón</button>
tendremos que escribir lo siguiente:
Muy fácil como veis. Ahora solo queda ver como enviar todos los shortcodes que creemos de este modo a nuestro servicio ShortcodeService
Sin tener que inyectar manualmente uno por uno en su constructor
Es decir, en vez de hacer ésto:
class ShortcodeService { public function __construct(ShortcodeWell $sw, $ShortcodeModal $m, more shortcodes) { $this->shortcodes[] = $sw; $this->shortcodes[] = $m; //etc etc etc }}
podemos etiquetar todos los servicios Shortcode de una misma forma y recogerlos en un Compiler Pass
para enviarlos de golpe a nuestro servicio, lo cual nos ahorra tener que tocar el constructor cada vez que añadamos uno nuevo (principio open-close).
Vamos a ver cómo hacerlo
Conectando nuestro shortcode con el servicio que los procesa
Para llevar a cabo el proceso que os contaba antes, lo primero de todo será definir una tag
para identificar a todos nuestros servicios que implementen la interfaz ShortcodeInterface
dentro del container
. Para ello retocaremos la interfaz un poquito:
Y en nuestro archivo services.yaml
indicaremos que nuestro servicio va etiquetado de esa forma:
App\Shortcode\ButtonShortcode:
tags:
- { name: lac.shortcode }
A continuación, añadiremos un método en nuestro ShortcodeService
que permita añadir elementos al array de shortcodes:
class ShortcodeService { // rest of code public function getShortcodes(): array { return $this->shortcodes; }
public function addShortcode(ShortcodeInterface $shortcode) { $this->shortcodes[$shortcode->getName()] = $shortcode; }}
Y, finalmente, la magia. Crearemos un CompilerPass
para recoger todos servicios etiquetados con lac.shortcode
y pasárselos al método addShortcode
:
Fácil y sencillo. Ahora cada servicio etiquetado como lac.shortcode
será directamente añadido al array de shortcodes de ShortcodeService
y podrá ser procesado sin tener que hacer nada más.
Y de este modo ya tenéis una forma de crear shortcodes en vuestro proyecto de Symfony. Espero que os haya servido!
Pd. Si queréis leer más acerca de los CompilerPass
podéis hacerlo en la documentación oficial, que como siempre es de gran ayuda:
¿Quieres recibir más artículos como este?
Suscríbete a nuestra newsletter: