Zum Hauptinhalt springen

Was sind Modell-Events?

Eloquent-Modelle lösen an bestimmten Punkten ihres Lebenszyklus automatisch Events aus. Indem Sie sich an diese Events hängen, können Sie vor oder nach dem Speichern, Löschen usw. eigene Logik einschleusen. Die von Eloquent ausgelösten Events sind:
EventZeitpunkt
retrievedNachdem das Modell aus der Datenbank geladen wurde
creatingUnmittelbar vor dem Speichern eines neuen Modells
createdUnmittelbar nach dem Speichern eines neuen Modells
updatingUnmittelbar vor dem Aktualisieren eines bestehenden Modells
updatedUnmittelbar nach dem Aktualisieren eines bestehenden Modells
savingUnmittelbar vor dem Speichern (Neuanlage oder Update)
savedUnmittelbar nach dem Speichern (Neuanlage oder Update)
deletingUnmittelbar vor dem Löschen eines Modells
deletedUnmittelbar nach dem Löschen eines Modells
trashedUnmittelbar nach einem Soft Delete
forceDeletingUnmittelbar vor einem harten Löschen
forceDeletedUnmittelbar nach einem harten Löschen
restoringUnmittelbar vor dem Wiederherstellen eines Soft-Deletes
restoredUnmittelbar nach dem Wiederherstellen eines Soft-Deletes
replicatingBeim Aufruf von replicate()
Events, die auf -ing enden, feuern vor der Persistierung in die DB, Events auf -ed danach.
Bei Massen-Updates oder Massen-Deletes (z. B. User::where(...)->update(...)) werden die Events saving, saved, updating, updated, deleting, deleted nicht ausgelöst, weil die Modelle nicht instanziiert werden.

Event-Listener über Closures

Für einfache Event-Behandlung können Sie Closures in der booted-Methode des Modells registrieren.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected static function booted(): void
    {
        static::created(function (User $user) {
            // Läuft nach dem Anlegen eines Nutzers
        });

        static::deleting(function (User $user) {
            // Läuft vor dem Löschen eines Nutzers
        });
    }
}
Um die Verarbeitung asynchron in einer Queue auszuführen, verwenden Sie den Helper queueable.
use function Illuminate\Events\queueable;

static::created(queueable(function (User $user) {
    // Wird asynchron in der Queue ausgeführt
}));

Property $dispatchesEvents

Wenn Sie das Laravel-Event-System nutzen möchten, ordnen Sie über die Property $dispatchesEvents Modell-Events eigenen Event-Klassen zu.
<?php

namespace App\Models;

use App\Events\UserDeleted;
use App\Events\UserSaved;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    /**
     * Zuordnung von Modell-Events zu Event-Klassen
     *
     * @var array<string, string>
     */
    protected $dispatchesEvents = [
        'saved' => UserSaved::class,
        'deleted' => UserDeleted::class,
    ];
}
Die zugeordneten Event-Klassen erhalten die Modell-Instanz per Konstruktor.
<?php

namespace App\Events;

use App\Models\User;

class UserSaved
{
    public function __construct(
        public readonly User $user,
    ) {}
}

Eine Observer-Klasse anlegen

Wenn Sie mehrere Events desselben Modells bündeln möchten, ist eine Observer-Klasse übersichtlicher als eine Reihe von Closures.
1

Klasse per Artisan-Command erzeugen

Erzeugen Sie ein Gerüst mit make:observer. Mit der Option --model erhalten Sie passende Methoden.
php artisan make:observer UserObserver --model=User
Die Datei app/Observers/UserObserver.php wird angelegt.
2

Methoden je Event implementieren

Der Methodenname entspricht dem Event-Namen. Als Argument erhalten Sie die Modell-Instanz.
<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
    public function created(User $user): void
    {
        // Verarbeitung nach dem Anlegen des Nutzers
    }

    public function updated(User $user): void
    {
        // Verarbeitung nach dem Aktualisieren
    }

    public function deleted(User $user): void
    {
        // Verarbeitung nach dem Löschen
    }

    public function restored(User $user): void
    {
        // Verarbeitung nach dem Wiederherstellen eines Soft-Deletes
    }

    public function forceDeleted(User $user): void
    {
        // Verarbeitung nach hartem Löschen
    }
}
3

Observer am Modell registrieren

Es gibt zwei Registrierungsvarianten. In Laravel 13 wird das Attribut #[ObservedBy] empfohlen.Variante 1: Attribut #[ObservedBy] (empfohlen)Sie versehen die Modellklasse mit dem Attribut — die Registrierung ist damit abgeschlossen. Änderungen am AppServiceProvider sind nicht nötig.
<?php

namespace App\Models;

use App\Observers\UserObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Foundation\Auth\User as Authenticatable;

#[ObservedBy(UserObserver::class)]
class User extends Authenticatable
{
    //
}
Zum Registrieren mehrerer Observer wiederholen Sie das Attribut oder übergeben ein Array.
#[ObservedBy(UserObserver::class)]
#[ObservedBy(AuditObserver::class)]
class User extends Authenticatable
{
    //
}
Variante 2: Registrierung im AppServiceProviderRufen Sie in der boot-Methode observe auf.
<?php

namespace App\Providers;

use App\Models\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        User::observe(UserObserver::class);
    }
}
Das Attribut #[ObservedBy] liegt im Namensraum Illuminate\Database\Eloquent\Attributes und ist native PHP-Syntax ab 8.0, die Laravel 13 aktiv einsetzt.

Observer innerhalb von Datenbanktransaktionen

Werden Modelle innerhalb einer Transaktion erstellt oder aktualisiert, wollen Sie den Observer manchmal erst nach dem Commit ausführen. Implementieren Sie dazu das Interface ShouldHandleEventsAfterCommit.
<?php

namespace App\Observers;

use App\Models\User;
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;

class UserObserver implements ShouldHandleEventsAfterCommit
{
    public function created(User $user): void
    {
        // Läuft nach dem Commit der Transaktion
    }
}
Wird außerhalb einer Transaktion gearbeitet, läuft der Observer wie gewohnt sofort.

Events temporär deaktivieren

withoutEvents — Events während eines Codeabschnitts unterdrücken

Innerhalb der an User::withoutEvents() übergebenen Closure werden keinerlei Modell-Events ausgelöst.
use App\Models\User;

$user = User::withoutEvents(function () {
    User::findOrFail(1)->delete();

    return User::find(2);
});

saveQuietly — Events beim Speichern unterdrücken

Wenn Sie ein Modell speichern wollen, ohne Events auszulösen, nutzen Sie saveQuietly.
$user = User::findOrFail(1);

$user->name = 'Victoria Faith';

$user->saveQuietly();
Analog gibt es Methoden für Löschen, Wiederherstellen und Replizieren.
$user->deleteQuietly();
$user->restoreQuietly();

Praktische Anwendungsfälle

Cache automatisch invalidieren

Wenn ein Modell aktualisiert oder gelöscht wird, den zugehörigen Cache automatisch leeren.
<?php

namespace App\Observers;

use App\Models\Post;
use Illuminate\Support\Facades\Cache;

class PostObserver
{
    public function saved(Post $post): void
    {
        Cache::forget("post:{$post->id}");
        Cache::forget('posts:latest');
    }

    public function deleted(Post $post): void
    {
        Cache::forget("post:{$post->id}");
        Cache::forget('posts:latest');
    }
}

Audit-Logs schreiben

Änderungshistorien automatisch protokollieren. Mit getDirty() erhalten Sie die Werte vor und nach der Änderung.
<?php

namespace App\Observers;

use App\Models\AuditLog;
use App\Models\User;

class UserObserver
{
    public function updating(User $user): void
    {
        AuditLog::create([
            'model_type' => User::class,
            'model_id'   => $user->id,
            'changes'    => $user->getDirty(),
            'user_id'    => auth()->id(),
        ]);
    }

    public function deleted(User $user): void
    {
        AuditLog::create([
            'model_type' => User::class,
            'model_id'   => $user->id,
            'changes'    => ['deleted' => true],
            'user_id'    => auth()->id(),
        ]);
    }
}
Das Event updating feuert vor der Persistierung in die DB — hier liefert getDirty() die geplanten neuen Werte. Nach dem Event updated ist getDirty() bereits leer.

Verknüpfte Modelle automatisch aktualisieren

Beispiel: Nach Abschluss einer Bestellung den Lagerbestand automatisch anpassen.
<?php

namespace App\Observers;

use App\Models\Order;

class OrderObserver
{
    public function created(Order $order): void
    {
        foreach ($order->items as $item) {
            $item->product->decrement('stock', $item->quantity);
        }
    }

    public function deleted(Order $order): void
    {
        foreach ($order->items as $item) {
            $item->product->increment('stock', $item->quantity);
        }
    }
}

Nächste Schritte

Fortgeschritten: PHP-Attribute

Lernen Sie die PHP-Attribute von Laravel 13 inklusive #[ObservedBy] im Überblick.
Zuletzt geändert am 13. Juli 2026