Symfony2: Custom Events

Seguimos con eventos, pero en esta ocasión veremos cómo crear los nuestros propios y qué ventajas nos ofrece usar eventos, para el ejemplo vamos a basarnos en FOSCommentBundle, nos crearemos un evento que se lanzará cuando se haga un comentario, nos crearemos un listener que le añada la IP al comentario, otro que compruebe que no tiene ninguna palabra prohibida, en cuyo caso pararemos la propagación, y finalmente uno que envía un correo al usuario notificándole de que el comentario se ha publicado.

Tenemos el siguiente modelo para el comentario:

Ahora creamos la clase que contendrá los nombres de los eventos que se van a lanzar:

Seguimos con la propia clase evento, esta clase sólo servirá de contenedor, podríamos usar GenericEvent, pero nos crearemos la nuestra para ver cómo sería:

Creamos el listener que añadirá la IP al comentario:

Creamos el listener que comprueba el contenido del mensaje, en este caso crearemos un subscriber (por usar los dos tipos):

Y añadimos el listener que mandará un correo para notificar al usuario:

No hemos implementado el envío del correo ya que nos estamos centrando en los eventos.

Finalmente registramos los listeners en nuestro listeners.xml:

Como nuestro listener que asigna la IP necesita la request para obtenerla, hay que declarar el servicio con scope request.

El parámetro banner_words lo hemos definido en config.yml:

Haciendo un breve repaso, tenemos:

  • La clase Comment para guardar un comentario.
  • La clase CommentEvents donde definimos el nombre de los eventos.
  • La clase CommentEvent que será el evento que se pase a los listeners.
  • Los listeners:
    • CommentIpListener que añadirá la IP al comentario y tiene prioridad 5, por lo que se ejecutará el primero.
    • CommentBannedWordsSubscriber que comprobará si alguna de las palabras del mensaje está prohibida y tiene prioridad 0.
    • CommentMailerSubscriber que envía un correo al usuario que ha hecho el comentario notificándole que se ha publicado y se ejecutará el último al tener prioridad -5.

Según las prioridades que hemos indicado, si dentro del mensaje hay palabras reservadas no se llamará al listener de envío de email.

Nos queda por crear un CommentType:

Y finalmente la acción del controller donde se lanzará el evento:

El controller lo único que se hace es lanzar el evento una vez que el formulario del comentario se ha completado correctamente.

Ventajas

Podríamos ir añadiendo listeners para comprobar si es spam, parsear si el mensaje está en algún formato especial, asignarlo a un usuario del sistema, etc. Todo eso sin tocar el controller, por lo que nos permite extender la funcionalidad sin modificar la clase donde se lanzan los eventos ni tenemos que añadir dependencias, quedando desacoplada.

Ver demo