13.
RAD with Symfony 3.3
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.
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
Whoops, an error! Please, try again later.
8 Comments
I really like that you remind us of old principles by example how auto wiring works, even if you thought it several videos before. Nice!
There is only one drawback with EventSubscribers against EventListeners.
EventListener can be defined as lazy, but EventSubscriber will be instantiated on every request.
Hey NothingWeAre!
That's *almost* correct :). Well, it IS correct, but with one small clarification: Symfony event subscribers are listeners are both lazy - there is zero difference. However, if you are making a Doctrine listener, then Doctrine event subscribers are indeed *always* instantiated. Doctrine event listeners *can* be made lazy, but actually are *not* lazy by default: you need to add a lazy: true option to the tag. Actually, this was fixed recently, and Doctrine listeners will always be lazy in Symfony 4.2 (https://github.com/symfony/... - but indeed, Doctrine event subscribers still won't be lazy (they can't be, unfortunately, because of the way the Doctrine event system is designed).
This is not a point most people think about - I'm glad you are ;).
Cheers!
In my experience Symfony kernel event bus always instantiate all listeners and subscribers, eventually, on every request where at least one event was fired.
Because I had events that depend on services, which depended on even more services, initialization graph had grown too much to my liking, regardless of the fact that each service was rather small. While some dependencies was cut in process of optimisation, in cases where it was not possible we decided to rely on lazy event listeners using ProxyManager (https://symfony.com/doc/cur.... And, with this approach event subscribers cannot be lazy, because they need to call getSubscribedEvents. On the other hand event listeners would be fully instantiated only when related event is fired and on..... function is called.
While this can also be achieved with Service Subscriber and accessing related service in function, we prefer Proxy approach with dependencies in __constructor, because it simplifies injecting them during testing.
Hey NothingWeAre!
Ahhhh! Now I understand better! Yea, event listeners (or subscribers) are a key place where the dependency graph can become a problem. It's really a problem whenever you are listening to an event that happens on every request - like kernel.request. The trick is that event subscribers *are* lazy: your object is not instantiated *unless* the event they are listening to is fired. But, if you're listening to something like kernel.request, then your event subscriber WILL be instantiated on every request because it needs to be called. That is especially a problem if your listener/subscriber needs to be called on every request, but then you only perform some actions ever 100th request (e.g. maybe a listener checks some info on the user, and if some rare condition is met, more action is taken). In these cases, (A) your listener/subscriber is instantiated which (of course) cases (B) all of your dependent services to be instantiated, but then (C) on most requests, you don't even use most of the services that were instantiated.
Phew! But, what I'm not sure about from your comment is how making your event listeners lazy via the ProxyManager would help with this. Event subscribers are naturally already lazy: they are only instantiated when they specific event they listen to is fired (if you're not seeing this behavior, it may be possible you're on an older version of Symfony where this wasn't as optimized). Event listeners are also naturally lazy... you shouldn't need to use the proxy with them. If you're seeing something different, definitely let me know what version of Symfony you are on. As I mentioned above, *usually* you need to worry about making the services that your listener/subscriber depends on lazy, not the listener/subscriber themselves.
Ok... too long of a answer/question from me :). Let me know what your situation is!
Cheers!
Thanks for reply.
I do not know what am I doing wrong, but I have tried to watch constructor of event listener with debugger and class that listens/subscribes for "security.authentication.failure" is instantiated on every request, regardless if concerned event is fired. While function call really are executed only on related event.
I think that it is related to deprecated class ContainerAwareEventDispatcher, which is used for listeners/subscribers management in our Symfony instalation (we are still using 3.3).
Hey NothingWeAre!
Yes, I think you're correct! And, after doing some digging, it looks like the event subscribes were not made fully lazy until Symfony 3.4 (and part of the reason it wasn't lazy before was due to ContainerAwareEventDispatcher). Here is the PR that made them finally lazy: https://github.com/symfony/...
So, that at least explains it :). In 3.4, your subscribers are lazy, but they may indeed not be before.
Cheers!
This is great!
"Houston: no signs of life"
Start the conversation!