Eigene Events und Listener
Eigene Events und Listener
~17 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026
Jetzt bauen wir das konkrete Feature aus Kapitel 5: eine Benachrichtigung, sobald eine Aufgabe einem Nutzer zugewiesen wird – mit einem EIGENEN, benannten Event, GENAU nach dem Muster der Kernel Events aus Kapitel 35.
Eine Event-Klasse erstellen
<?php
declare(strict_types=1);
namespace App\Event;
use App\Entity\Task;
use App\Entity\User;
use Symfony\Contracts\EventDispatcher\Event;
class AufgabeZugewiesenEvent extends Event
{
public function __construct(
private readonly Task $aufgabe,
private readonly User $zugewiesenerNutzer,
) {
}
public function getAufgabe(): Task
{
return $this->aufgabe;
}
public function getZugewiesenerNutzer(): User
{
return $this->zugewiesenerNutzer;
}
}Die Basisklasse Symfony\Contracts\EventDispatcher\Event ist bewusst MINIMAL gehalten – ein Event-Objekt ist im Kern ein einfacher, unveränderlicher Datenträger für den KONTEXT eines Ereignisses (WELCHE Aufgabe, WELCHER Nutzer).
Das Event im Service auslösen
<?php
declare(strict_types=1);
namespace App\Service;
use App\Entity\Task;
use App\Entity\User;
use App\Event\AufgabeZugewiesenEvent;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
class TaskZuweisungsService
{
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly EventDispatcherInterface $eventDispatcher,
) {
}
public function weiseZu(Task $aufgabe, User $nutzer): void
{
$aufgabe->setZugewiesenerNutzer($nutzer);
$this->entityManager->flush();
$this->eventDispatcher->dispatch(
new AufgabeZugewiesenEvent($aufgabe, $nutzer)
);
}
}EventDispatcherInterface ist – GENAU wie LoggerInterface – ein von Symfony bereitgestellter Service, per Autowiring verfügbar. dispatch() löst das Event aus: ALLE registrierten Listener für AufgabeZugewiesenEvent laufen SOFORT, SYNCHRON, in der Reihenfolge ihrer Priorität (Kapitel 35).
Achtung: TaskZuweisungsService WEISS NICHT, welche (falls überhaupt welche) Listener auf dieses Event reagieren – das ist BEABSICHTIGT, nicht ein Mangel an Information. Genau diese Entkopplung ist der Kernvorteil: Kapitel 38 fügt einen E-Mail-Listener hinzu, OHNE TaskZuweisungsService AUCH NUR ANZUFASSEN.
Einen Listener für unser eigenes Event
<?php
declare(strict_types=1);
namespace App\EventListener;
use App\Event\AufgabeZugewiesenEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
#[AsEventListener]
class AufgabeZugewiesenListener
{
public function __construct(
private readonly LoggerInterface $logger,
) {
}
public function __invoke(AufgabeZugewiesenEvent $event): void
{
$this->logger->info(sprintf(
'Aufgabe "%s" wurde %s zugewiesen.',
$event->getAufgabe()->getTitel(),
$event->getZugewiesenerNutzer()->getName(),
));
}
}OHNE explizites event: '...'-Argument (anders als bei kernel.exception in Kapitel 35) erkennt #[AsEventListener] das Event AUTOMATISCH am Typ des __invoke()-Parameters – ein weiterer Vorteil eigener, typisierter Event-Klassen gegenüber den älteren, NAMENSBASIERTEN Kernel Events.
Mehrere Listener für dasselbe Event
GENAU wie bei Kernel Events können BELIEBIG viele Listener auf AufgabeZugewiesenEvent reagieren – ein zweiter, unabhängiger Listener (z. B. für eine spätere Dashboard-Aktivitäts-Historie) würde EINFACH eine weitere #[AsEventListener]-Klasse mit demselben Event-Typ bedeuten, OHNE TaskZuweisungsService oder den ERSTEN Listener zu verändern.
Faustregel: wann lohnt sich ein eigenes Event?
| Ansatz | Wann geeignet |
|---|---|
| Direkter Methodenaufruf | Wenn es GENAU EINEN, festen Empfänger gibt und diese Beziehung sich wahrscheinlich NIE ändert. |
| Eigenes Event | Wenn ein Vorgang MEHRERE, potenziell WACHSENDE, voneinander UNABHÄNGIGE Reaktionen auslösen soll – wie unsere Aufgaben-Zuweisung, die künftig Logging, E-Mail, Push-Benachrichtigung UND Aktivitäts-Historie gleichzeitig bedienen könnte. |
Tipp: Ein häufiger Anfängerfehler: JEDEN Methodenaufruf zu einem Event machen "weil man es kann" – das macht den Codefluss SCHWERER nachvollziehbar ("wer reagiert eigentlich auf dieses Event?" wird zur echten Suche). Events lohnen sich GENAU dann, wenn Entkopplung einen ECHTEN, absehbaren Wert bietet – nicht als generelle Standard-Wahl.