Chapters
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3
Subscribe to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Keep on Learning!
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!
Messenger puede ser asíncrono
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.
El EventDispatcher se comunica de nuevo
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.
4 Comments
Hey @colonelclick ,
Difficult to say for sure. Well, you can't technically dispatch both at the same time right? So, anyway someone will be dispatched first, and so will be handled first too in case we're talking about sync. With first async and second sync - I suppose the 2nd will be handled first as it's sync event. Anyway, it would be better to debug it with dd()
or dump()
statements and you will know for sure. Also, if this is a crucial point of your app - add some tests to cover things, you will be sure about the order in this case, and you will be notified when something is changed because your tests will start failing.
I hope this helps!
Cheers!
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 ?
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!
"Houston: no signs of life"
Start the conversation!
What PHP libraries does this tutorial use?
// 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.21.6
"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
}
}
What would be handled first if I am dispatching both an event and a synchronous message during the request lifecycle? I understand how to set the priority of events relative to each other, but how does priority work with a mixture of events, synchronous messages, and subscribers?