Nicolas Grekas
Contributed by Nicolas Grekas in #28920

In Symfony 3.3, we made the class optional for named services and started recommending to use the fully-qualified class name (FQCN) as the service ID. This makes config more intuitive and helps you avoid thinking about arbitrary strings to name services.

Following the same idea, in Symfony 4.3 we've changed the signature of the EventDispatcherInterface::dispatch() method:

1
2
3
4
5
6
7
8
9
// ...
$order = new Order();
$newOrderEvent = new OrderPlacedEvent($order);

// Before
$dispatcher->dispatch(OrderEvents::NEW_ORDER, $newOrderEvent);

// After
$dispatcher->dispatch($newOrderEvent, OrderEvents::NEW_ORDER);

Although this change looks minor, it helps simplify the rest of the app code. For starters, you can subscribe to events using the FQCN of the event:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class StoreSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        // Before
        return [
            OrderEvents::NEW_ORDER => 'onStoreOrder',
        ];

        // After
        return [
            OrderPlacedEvent::class => 'onStoreOrder',
        ];
    }

    // ...
}

Moreover, the event name is now optional in the dispatch() method, so you can pass just the event object:

1
2
3
4
5
// Before
$dispatcher->dispatch(OrderEvents::NEW_ORDER, $newOrderEvent);

// After
$dispatcher->dispatch($newOrderEvent);

In summary, the new dispatch() signature allows you to develop code based on pure PHP classes instead of inventing arbitrary strings to name events.

Updated HttpKernel event classes

In addition to the previous change, we've also updated the classes of the events that Symfony passes for its own events. The new names are much more intuitive and concise:

  • Renamed FilterControllerArgumentsEvent to ControllerArgumentsEvent
  • Renamed FilterControllerEvent to ControllerEvent
  • Renamed FilterResponseEvent to ResponseEvent
  • Renamed GetResponseEvent to RequestEvent
  • Renamed GetResponseForControllerResultEvent to ViewEvent
  • Renamed GetResponseForExceptionEvent to ExceptionEvent
  • Renamed PostResponseEvent to TerminateEvent

Supporting both dispatchers

Bundles and packages that want to provide forward and/or backward compatibility with the new and old dispatch() methods can use the new LegacyEventDispatcherProxy class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;

class SomeService
{
    public function __construct(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher);
    }

    public function someMethod()
    {
        // ...

        // use the new way of dispatching events (with or without the event name)
        // even if the provided dispatcher still implements the legacy way
        $this->dispatcher->dispatch($newOrderEvent);
        $this->dispatcher->dispatch($newOrderEvent, OrderEvents::NEW_ORDER);
    }
}
Published in #Living on the edge