If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeSi alguna vez has creado un oyente de eventos o un suscriptor de eventos en Symfony, estás creando un "oyente" para un evento que se envía a través de un servicio llamado "despachador de eventos". El propósito del despachador de eventos es permitir que un trozo de código "notifique" a la aplicación que ha ocurrido algo y que cualquier otro "escuche" ese evento y ejecute algún código.
Lo cual... eh... es exactamente el mismo propósito de despachar un evento en Messenger ¿Qué demonios? Si quiero enviar un evento en mi código, ¿debo utilizar el EventDispatcher o el Messenger? ¿Los archivos de imágenes animadas se pronuncian "jif" o "gif"? ¿El papel higiénico debe colgar "encima" del rollo o "debajo"? ¡Ah!
En primer lugar, hay una diferencia práctica entre enviar un evento al EventDispatcher o al Messenger: Messenger permite llamar a sus manejadores de forma asíncrona, mientras que los oyentes de los eventos del EventDispatcher son siempre síncronos.
Y esto nos lleva a una buena regla general. Siempre que envíes un evento, si quieres que los oyentes de ese evento puedan comunicarse contigo, para que puedas hacer algo basándote en su respuesta, utiliza el EventDispatcher. Pero si simplemente quieres decir "ha pasado esto" y no necesitas ninguna respuesta de los posibles oyentes o manejadores, utiliza Messenger.
Por ejemplo, en AddPonkaToImageHandler
, supongamos que queremos enviar un evento aquí para que otras partes del sistema nos digan exactamente qué imagen Ponka debe añadirse a esta foto. En ese caso, necesitamos que esos oyentes puedan comunicarse con nosotros. Para ello, crearíamos una clase de Evento que contenga el objeto ImagePost
y que tenga un definidor al que los oyentes puedan llamar, tal vezsetPonkaImageToUse()
. Entonces utilizaríamos el EventDispatcher
y enviaríamos el mensaje antes de añadir realmente Ponka a la imagen. Una vez llamados todos los oyentes, podríamos ver si alguno de ellos llama a ese método setPonkaImageToUse()
.
Pero, ¿y si simplemente quisiéramos decir:
¡Oye! ¡Acabamos de añadir a Ponka a una imagen!
... y no necesitáramos ninguna información de los posibles manejadores? En ese caso, crearíamos una clase de evento similar, omitiríamos el método setPonkaImageToUse()
y lo despacharíamos con Messenger. Messenger es perfecto si no necesitas ninguna información de vuelta de tus manejadores porque... ¡esos manejadores podrían acabar siendo llamados de forma asíncrona!
Si todavía no lo tienes claro, utiliza el que quieras. ¿Por qué? Porque si al final quieres que tu código se ejecute de forma asíncrona, acabarás eligiendo Messenger. Y si quieres que tus oyentes puedan comunicarse con el código que envía los mensajes, utilizarás EventDispatcher. De lo contrario, cualquiera de los dos funcionará.
A continuación, vamos a utilizar algunos trucos de configuración del servicio para ajustar cómo hemos organizado nuestros comandos, manejadores de comandos, eventos y manejadores de eventos.
Hey erop!
That's basically how I think about it :). Or, to say it a slightly different way, I use EventDispatcher for adding "hooks" to my code (which I don't do very often - but that's a matter of taste - it's something much more common for re-usable libraries) and Messenger for (as you said) my domain events/messages.
But, this gets very fuzzy in some cases. Like, suppose I want to dispatch an "event" after a user register. Should I use event dispatcher because I see this as a "hook" for other parts of my code to do something? Or should I use Messenger... because this is a domain event. I could really see either... which also means that, in my opinion (which tends to be pretty relaxed), either solution would be "ok" :).
Cheers!
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-ctype": "*",
"ext-iconv": "*",
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/annotations": "^1.0", // v1.8.0
"doctrine/doctrine-bundle": "^1.6.10", // 1.11.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.6.3
"intervention/image": "^2.4", // 2.4.2
"league/flysystem-bundle": "^1.0", // 1.1.0
"phpdocumentor/reflection-docblock": "^3.0|^4.0", // 4.3.1
"sensio/framework-extra-bundle": "^5.3", // v5.3.1
"symfony/console": "4.3.*", // v4.3.2
"symfony/dotenv": "4.3.*", // v4.3.2
"symfony/flex": "^1.9", // v1.18.7
"symfony/framework-bundle": "4.3.*", // v4.3.2
"symfony/messenger": "4.3.*", // v4.3.4
"symfony/property-access": "4.3.*", // v4.3.2
"symfony/property-info": "4.3.*", // v4.3.2
"symfony/serializer": "4.3.*", // v4.3.2
"symfony/validator": "4.3.*", // v4.3.2
"symfony/webpack-encore-bundle": "^1.5", // v1.6.2
"symfony/yaml": "4.3.*" // v4.3.2
},
"require-dev": {
"easycorp/easy-log-handler": "^1.0.7", // v1.0.7
"symfony/debug-bundle": "4.3.*", // v4.3.2
"symfony/maker-bundle": "^1.0", // v1.12.0
"symfony/monolog-bundle": "^3.0", // v3.4.0
"symfony/stopwatch": "4.3.*", // v4.3.2
"symfony/twig-bundle": "4.3.*", // v4.3.2
"symfony/var-dumper": "4.3.*", // v4.3.2
"symfony/web-profiler-bundle": "4.3.*" // v4.3.2
}
}
Ryan, your explanation about difference between Messenger and EventDispatcher is pretty clear. But we could also use Messenger for synchronous message (command/query/event) processing. So what do you thing of using EventDispatcher only for handling kernel's lifecycle-connected events while using Messenger specifically for domain events (NewProductAdded, etc.) both in a sync (i.e. not listed in framework.messenger.routing) and async ways ?