Events
An event is a message saying "this happened". The code that sent it does not know who will react. That lets you add new consequences to an action — an email, a log entry, recalculated statistics — without touching the original code. Symfony itself is built on events.
A kernel event listener
While Symfony handles a request, it dispatches several events. A listener is a class with the #[AsEventListener] attribute:
// src/EventListener/ResponseHeaderListener.php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
#[AsEventListener]
class ResponseHeaderListener
{
public function __invoke(ResponseEvent $event): void
{
$event->getResponse()->headers->set('X-Frame-Options', 'DENY');
}
}Symfony works out which event to listen to from the argument type. The header is now added to every response.
Kernel events
| Event | When it happens |
|---|---|
RequestEvent | The request arrived, no controller chosen yet |
ControllerEvent | The controller is chosen but not called |
ResponseEvent | The response is ready to be sent |
ExceptionEvent | An exception occurred |
TerminateEvent | The response has already been sent |
Your own event
An event is a plain class with data:
// src/Event/PostPublished.php
namespace App\Event;
use App\Entity\Post;
class PostPublished
{
public function __construct(public readonly Post $post) {}
}The dispatcher sends it:
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
public function publish(Post $post, EntityManagerInterface $em, EventDispatcherInterface $dispatcher): Response
{
$post->setPublished(true);
$em->flush();
$dispatcher->dispatch(new PostPublished($post));
return $this->redirectToRoute('blog_show', ['id' => $post->getId()]);
}Listeners for your event
#[AsEventListener]
class NotifySubscribers
{
public function __construct(private MailerInterface $mailer) {}
public function __invoke(PostPublished $event): void
{
// email the subscribers about $event->post
}
}There can be any number of listeners. The controller knows nothing about them.
A subscriber
A subscriber is a class that listens to several events and lists them itself:
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
class LocaleSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => ['onRequest', 20],
];
}
public function onRequest(RequestEvent $event): void
{
$request = $event->getRequest();
$request->setLocale($request->getSession()->get('locale', 'en'));
}
}The number 20 is the priority: the larger it is, the earlier the method is called.
Doctrine events
An entity can react to its own saving:
#[ORM\Entity]
#[ORM\HasLifecycleCallbacks]
class Post
{
#[ORM\PrePersist]
public function setCreatedAtValue(): void
{
$this->createdAt = new \DateTimeImmutable();
}
}Listing listeners
php bin/console debug:event-dispatcher
php bin/console debug:event-dispatcher kernel.requestCommon mistake
Kernel event listeners run on every request. Slow work in them — a call to an external service, a heavy calculation — slows the whole site. Long tasks are sent from a listener to a queue, and the listener itself stays short.