Zum Hauptinhalt springen

Was sind Events?

Das Event-System von Laravel ist eine schlanke Umsetzung des Observer-Musters. Sie feuern innerhalb der Anwendung Ereignisse (Events) und definieren Listener, die darauf reagieren – Abhängigkeiten zwischen Komponenten bleiben so minimal. Wird zum Beispiel das Event „Bestellung wurde bestätigt” ausgelöst, arbeiten mehrere Listener unabhängig voneinander: „Bestätigungs-E-Mail versenden”, „Bestand reduzieren”, „Slack benachrichtigen”. Die Bestellungslogik selbst muss weder E-Mail-Versand noch Slack-Notifications kennen.
Event-Klassen liegen im Verzeichnis app/Events, Listener-Klassen in app/Listeners. Existieren die Verzeichnisse noch nicht, legen die Artisan-Befehle sie automatisch an.

Events und Listener erzeugen

Mit den Artisan-Befehlen make:event und make:listener erstellen Sie das jeweilige Grundgerüst.
php artisan make:event UserRegistered

php artisan make:listener SendWelcomeEmail --event=UserRegistered
Ohne Argument fragt der Befehl die Angaben interaktiv ab.
php artisan make:event

php artisan make:listener

Events registrieren

Event Discovery (automatisch)

Standardmäßig durchsucht Laravel das Verzeichnis app/Listeners und registriert Listener automatisch. Die Zuordnung zu einem Event erfolgt anhand des Argumenttyps der Methode handle bzw. __invoke.
use App\Events\UserRegistered;

class SendWelcomeEmail
{
    public function handle(UserRegistered $event): void
    {
        // Willkommens-E-Mail senden
    }
}
Mit PHP-Union-Types kann eine Methode auf mehrere Events reagieren.
public function handle(UserRegistered|UserUpdated $event): void
{
    // ...
}
Legen Sie Ihre Listener in ein anderes Verzeichnis, geben Sie zusätzliche Suchpfade in bootstrap/app.php an.
->withEvents(discover: [
    __DIR__.'/../app/Domain/Orders/Listeners',
])
Mit einem Wildcard-Muster erfassen Sie mehrere Verzeichnisse in einer Angabe.
->withEvents(discover: [
    __DIR__.'/../app/Domain/*/Listeners',
])
Alle registrierten Listener sehen Sie mit dem folgenden Befehl:
php artisan event:list
Cachen Sie das Listener-Manifest in der Produktion für bessere Performance. Führen Sie beim Deployment php artisan optimize oder php artisan event:cache aus. Zum Löschen des Caches verwenden Sie php artisan event:clear.

Manuelle Registrierung

Sie können Listener in der boot-Methode Ihres AppServiceProvider über die Event-Facade auch manuell registrieren.
use App\Events\UserRegistered;
use App\Listeners\SendWelcomeEmail;
use Illuminate\Support\Facades\Event;

public function boot(): void
{
    Event::listen(
        UserRegistered::class,
        SendWelcomeEmail::class,
    );
}
Auch die Registrierung über eine Closure ist möglich.
use App\Events\UserRegistered;
use Illuminate\Support\Facades\Event;

public function boot(): void
{
    Event::listen(function (UserRegistered $event) {
        // ...
    });
}

Events definieren

Event-Klassen sind einfache Datenträger. Sie enthalten keine Logik, sondern halten die zum Event gehörenden Informationen als Properties.
<?php

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class UserRegistered
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct(
        public User $user,
    ) {}
}
Das Trait SerializesModels sorgt dafür, dass Eloquent-Modelle beim Serialisieren des Events für die Queue korrekt behandelt werden.

Events auslösen

Feuern Sie Events über die statische Methode dispatch oder den Helper event().
use App\Events\UserRegistered;

// Statische Methode
UserRegistered::dispatch($user);

// Helper-Funktion
event(new UserRegistered($user));
Für bedingtes Auslösen stehen ebenfalls Methoden bereit.
UserRegistered::dispatchIf($condition, $user);

UserRegistered::dispatchUnless($condition, $user);

Auslösen nach einer Datenbanktransaktion

Möchten Sie ein Event erst nach dem Commit einer Transaktion auslösen, implementieren Sie in der Event-Klasse ShouldDispatchAfterCommit. Bei einem Rollback wird das Event verworfen.
<?php

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class UserRegistered implements ShouldDispatchAfterCommit
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct(
        public User $user,
    ) {}
}

Listener implementieren

Ein Listener empfängt das Event in der Methode handle. Abhängigkeiten im Konstruktor löst der Service Container automatisch auf.
<?php

namespace App\Listeners;

use App\Events\UserRegistered;
use App\Mail\WelcomeMail;
use Illuminate\Support\Facades\Mail;

class SendWelcomeEmail
{
    public function __construct() {}

    public function handle(UserRegistered $event): void
    {
        Mail::to($event->user->email)
            ->send(new WelcomeMail($event->user));
    }
}
Gibt die Methode handle false zurück, wird die Weitergabe des Events an nachfolgende Listener gestoppt.

Listener in der Queue

Zeitaufwendige Aufgaben – etwa E-Mail-Versand oder HTTP-Anfragen – können asynchron in einer Queue laufen. Es genügt, das Interface ShouldQueue zu implementieren; beim Auslösen des Events wird der Listener automatisch in die Queue gestellt.
<?php

namespace App\Listeners;

use App\Events\UserRegistered;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendWelcomeEmail implements ShouldQueue
{
    public function handle(UserRegistered $event): void
    {
        // Wird vom Queue-Worker asynchron ausgeführt
    }
}
Vor der Nutzung von queued Listenern müssen Sie die Queue konfigurieren und einen Worker starten. Details finden Sie auf der Seite Queues und Jobs.

Connection, Queue-Name und Delay anpassen

Über PHP-Attribute legen Sie Zielverbindung, Queue-Name und Verzögerung fest.
<?php

namespace App\Listeners;

use App\Events\UserRegistered;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\Attributes\Connection;
use Illuminate\Queue\Attributes\Delay;
use Illuminate\Queue\Attributes\Queue;

#[Connection('redis')]
#[Queue('emails')]
#[Delay(10)]
class SendWelcomeEmail implements ShouldQueue
{
    public function handle(UserRegistered $event): void
    {
        // ...
    }
}
Auch dynamische Werte über Methoden sind möglich.
public function viaConnection(): string
{
    return 'redis';
}

public function viaQueue(): string
{
    return 'emails';
}

public function withDelay(UserRegistered $event): int
{
    return 10;
}

Anzahl Versuche und Timeout

Mit den Attributen #[Tries] und #[Timeout] steuern Sie das Verhalten bei Fehlschlägen.
use Illuminate\Queue\Attributes\Tries;
use Illuminate\Queue\Attributes\Timeout;

#[Tries(3)]
#[Timeout(30)]
class SendWelcomeEmail implements ShouldQueue
{
    // ...
}

Fehlerbehandlung

Definieren Sie die Methode failed, um nach überschrittener Versuchsanzahl aufzuräumen.
use Throwable;

public function failed(UserRegistered $event, Throwable $exception): void
{
    // Administrator benachrichtigen usw.
}

Event-Subscriber

Event-Subscriber fassen mehrere zusammengehörige Event-Handler in einer Klasse zusammen.

Subscriber erstellen

Aus der Methode subscribe geben Sie ein Array zurück, das Events auf Handler-Methoden abbildet.
<?php

namespace App\Listeners;

use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;

class UserActivitySubscriber
{
    public function handleLogin(Login $event): void
    {
        // Login verarbeiten
    }

    public function handleLogout(Logout $event): void
    {
        // Logout verarbeiten
    }

    /**
     * @return array<string, string>
     */
    public function subscribe(Dispatcher $events): array
    {
        return [
            Login::class => 'handleLogin',
            Logout::class => 'handleLogout',
        ];
    }
}

Subscriber registrieren

Ist Event Discovery aktiv, werden Subscriber, deren subscribe-Methode ein Array zurückgibt, automatisch registriert. Für eine manuelle Registrierung nutzen Sie in der boot-Methode Ihres AppServiceProvider Event::subscribe.
use App\Listeners\UserActivitySubscriber;
use Illuminate\Support\Facades\Event;

public function boot(): void
{
    Event::subscribe(UserActivitySubscriber::class);
}

Praxisbeispiel: Willkommens-E-Mail bei Registrierung senden

1

Event-Klasse erstellen

php artisan make:event UserRegistered
Ergänzen Sie in app/Events/UserRegistered.php eine Property für den registrierten Nutzer.
<?php

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class UserRegistered
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct(
        public User $user,
    ) {}
}
2

Listener-Klasse erstellen

php artisan make:listener SendWelcomeEmail --event=UserRegistered
Um den E-Mail-Versand asynchron über die Queue auszuführen, implementieren Sie ShouldQueue.
<?php

namespace App\Listeners;

use App\Events\UserRegistered;
use App\Mail\WelcomeMail;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Mail;

class SendWelcomeEmail implements ShouldQueue
{
    public function handle(UserRegistered $event): void
    {
        Mail::to($event->user->email)
            ->send(new WelcomeMail($event->user));
    }
}
3

Event im Controller auslösen

Nach der Registrierung rufen Sie UserRegistered::dispatch() auf.
<?php

namespace App\Http\Controllers\Auth;

use App\Events\UserRegistered;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class RegisterController extends Controller
{
    public function store(Request $request): RedirectResponse
    {
        $user = User::create($request->validated());

        UserRegistered::dispatch($user);

        return redirect('/dashboard');
    }
}
Der RegisterController löst nur das Event UserRegistered aus und weiß nichts vom E-Mail-Versand. Auch wenn später eine Slack-Benachrichtigung dazukommt, bleibt der Controller unverändert.
4

Worker starten

Um queued Listener zu verarbeiten, starten Sie einen Queue-Worker.
php artisan queue:work
Ist Event Discovery aktiv, ist keine manuelle Registrierung im AppServiceProvider nötig. Listener in app/Listeners werden automatisch erkannt.
Mit php artisan event:list prüfen Sie die Liste registrierter Events und Listener. Kontrollieren Sie regelmäßig, ob keine unerwarteten Listener registriert sind.
Zuletzt geändert am 13. Juli 2026