Vai al contenuto principale

Cosa sono gli eventi del modello

I modelli Eloquent emettono automaticamente eventi nei diversi momenti del ciclo di vita. Agganciandoti a questi eventi puoi inserire logica prima e dopo il salvataggio, la cancellazione, ecc. Gli eventi emessi da Eloquent sono i seguenti.
EventoMomento di emissione
retrievedModello letto dal DB
creatingSubito prima di salvare un nuovo modello
createdSubito dopo aver salvato un nuovo modello
updatingSubito prima di aggiornare un modello esistente
updatedSubito dopo aver aggiornato un modello esistente
savingSubito prima di salvare (creazione o aggiornamento)
savedSubito dopo aver salvato (creazione o aggiornamento)
deletingSubito prima di cancellare un modello
deletedSubito dopo aver cancellato un modello
trashedSubito dopo il soft delete
forceDeletingSubito prima della cancellazione fisica
forceDeletedSubito dopo la cancellazione fisica
restoringSubito prima di ripristinare un soft delete
restoredSubito dopo il ripristino di un soft delete
replicatingAlla chiamata di replicate()
Gli eventi che finiscono in -ing vengono emessi prima che la modifica sia persistita sul DB; quelli in -ed dopo.
Sugli aggiornamenti e le cancellazioni di massa (User::where(...)->update(...), ecc.), gli eventi saving, saved, updating, updated, deleting, deleted non vengono emessi, perché i modelli non vengono effettivamente recuperati.

Listener con closure

Per una gestione semplice degli eventi puoi registrare closure nel metodo booted del modello.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected static function booted(): void
    {
        static::created(function (User $user) {
            // logica eseguita dopo la creazione dell'utente
        });

        static::deleting(function (User $user) {
            // logica eseguita prima della cancellazione dell'utente
        });
    }
}
Per eseguire l’elaborazione in modo asincrono via queue, usa l’helper queueable.
use function Illuminate\Events\queueable;

static::created(queueable(function (User $user) {
    // eseguito in coda in modo asincrono
}));

Proprietà $dispatchesEvents

Se vuoi integrarti con il sistema eventi di Laravel, mappa gli eventi del modello a tue classi evento con la proprietà $dispatchesEvents.
<?php

namespace App\Models;

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

class User extends Authenticatable
{
    /**
     * Mapping tra eventi del modello e classi evento
     *
     * @var array<string, string>
     */
    protected $dispatchesEvents = [
        'saved' => UserSaved::class,
        'deleted' => UserDeleted::class,
    ];
}
La classe evento mappata riceve nel costruttore l’istanza del modello.
<?php

namespace App\Events;

use App\Models\User;

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

Creare una classe Observer

Quando gestisci più eventi per un unico modello, raggruppare in una classe Observer è più ordinato che elencare closure.
1

Generare la classe con Artisan

Genera lo scaffold con make:observer. Con l’opzione --model vengono aggiunti automaticamente i metodi corrispondenti.
php artisan make:observer UserObserver --model=User
Viene generato app/Observers/UserObserver.php.
2

Implementare i metodi per ciascun evento

Il nome del metodo corrisponde al nome dell’evento. L’argomento è l’istanza del modello.
<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
    public function created(User $user): void
    {
        // logica dopo la creazione dell'utente
    }

    public function updated(User $user): void
    {
        // logica dopo l'aggiornamento dell'utente
    }

    public function deleted(User $user): void
    {
        // logica dopo la cancellazione dell'utente
    }

    public function restored(User $user): void
    {
        // logica dopo il ripristino di un soft delete
    }

    public function forceDeleted(User $user): void
    {
        // logica dopo la cancellazione fisica
    }
}
3

Registrare l'Observer sul modello

Ci sono due modi. In Laravel 13 è consigliato l’attributo #[ObservedBy].Metodo 1: attributo #[ObservedBy] (consigliato)Basta applicare l’attributo alla classe del modello: nessuna modifica ad AppServiceProvider.
<?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
{
    //
}
Per registrare più Observer ripeti l’attributo o passa un array.
#[ObservedBy(UserObserver::class)]
#[ObservedBy(AuditObserver::class)]
class User extends Authenticatable
{
    //
}
Metodo 2: registrazione in AppServiceProviderNel metodo boot di AppServiceProvider chiami observe.
<?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);
    }
}
L’attributo #[ObservedBy] si trova nel namespace Illuminate\Database\Eloquent\Attributes. È sintassi nativa PHP dalla versione 8.0 ed è adottata attivamente in Laravel 13.

Observer dentro una transazione del database

Se un modello viene creato o aggiornato in una transazione, a volte vuoi che l’Observer venga eseguito dopo il commit. Implementando l’interfaccia ShouldHandleEventsAfterCommit ottieni questo comportamento.
<?php

namespace App\Observers;

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

class UserObserver implements ShouldHandleEventsAfterCommit
{
    public function created(User $user): void
    {
        // eseguito dopo il commit della transazione
    }
}
Fuori da una transazione l’esecuzione avviene immediatamente come al solito.

Disabilitare temporaneamente gli eventi

Fermare gli eventi solo per una specifica operazione con withoutEvents

Dentro la closure passata a User::withoutEvents() non viene emesso alcun evento del modello.
use App\Models\User;

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

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

Fermare gli eventi al salvataggio con saveQuietly

Per salvare un modello senza emettere eventi usa saveQuietly.
$user = User::findOrFail(1);

$user->name = 'Victoria Faith';

$user->saveQuietly();
Metodi analoghi sono disponibili per cancellazione, ripristino e replica.
$user->deleteQuietly();
$user->restoreQuietly();

Casi d’uso pratici

Invalidazione automatica della cache

Quando un modello viene aggiornato o cancellato, invalidi automaticamente le cache correlate.
<?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');
    }
}

Registrazione di audit log

Registri automaticamente la cronologia delle modifiche. Con getDirty() ottieni i valori prima e dopo la modifica.
<?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(),
        ]);
    }
}
L’evento updating viene emesso prima del salvataggio su DB, quindi puoi ottenere i valori in procinto di essere modificati con getDirty(). Se lo chiami dopo updated, getDirty() sarà vuoto.

Aggiornamento automatico di modelli correlati

Esempio in cui, al completamento di un ordine, il magazzino viene aggiornato automaticamente.
<?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);
        }
    }
}

Prossimi passi

Argomenti avanzati: attributi PHP

Impara insieme gli attributi PHP di Laravel 13, compreso #[ObservedBy].
Ultima modifica il 13 luglio 2026