Symfony: Be careful with eventClass vs. eventName
Fabian Blechschmidt
The examples are from Shopware 6.5.6.1.
Today I debugged code with my colleague Bruno. We had the problem, that our Subscriber triggers, but at the wrong moment. As Shopware developers, we often implement our subscribers using the eventClass. This method is commonly used „everywhere“ …
Well, not entirely… One small village of indomitable Gauls still holds out against the invaders.
Robert Steven Caron – Introduction of Asterix and Obelix
->dispatch() – How Shopware does it most of the time
Normally the dispatch code throughout most of the Shopware code base looks like this:
$event = new SomeEvent();
$this->eventDispatcher->dispatch($event);
To implement our subscriber we do:
class SomeSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
SomeEvent::class => 'doSomething'
];
}
// ...
}
Symfony: The whole picture of ->dispatch()
Nothing new here. We got so used to this that we forgot the whole picture. I thought it might be a good reminder for you as well about the basics of Symfony subscribers.
There are two options to define the event name, let’s have a look into \Symfony\Component\EventDispatcher\EventDispatcher::dispatch:
public function dispatch(object $event, ?string $eventName = null): object
{
$eventName ??= $event::class;
if (isset($this->optimized)) {
$listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName));
} else {
$listeners = $this->getListeners($eventName);
}
if ($listeners) {
$this->callListeners($listeners, $eventName, $event);
}
return $event;
}
As you can see, you can either pass the event and then the class name is used. Or you pass a second argument with an explicit event name.
\Shopware\Core\Framework\Validation\BuildValidationEvent
BuildValidationEvent is a nasty case. If you look through the code, it always uses an event name. This approach makes sense. You want to differ all the use cases.
$validationEvent = new BuildValidationEvent($definition, $data, $context);
$this->eventDispatcher->dispatch($validationEvent, $validationEvent->getName());
Except one case:
\Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoader::validateBillingAddress
$validationEvent = new BuildValidationEvent($validation, new DataBag(), $context->getContext());
$this->eventDispatcher->dispatch($validationEvent);
This was fixed in 6.6.8.0 (we don’t talk about backwards compatibility breaks and minor versions here…)
TL;DR
Be careful with $eventClasses and $eventNames. Make sure to not oversee it! If you use the wrong one your subscriber doesn’t work – how unexpected 😀
Other articles from this category