Vai al contenuto principale

Panoramica

Ogni volta che un modello Eloquent viene istanziato esegue due fasi: boot (una volta per classe) e initialize (una volta per istanza). Quando definisci metodi specifici in un trait, Eloquent li rileva e li invoca automaticamente. È sufficiente aggiungere il trait al modello. Laravel stesso utilizza questo pattern in modo estensivo in trait come SoftDeletes, HasUuids e HasUlids.

boot vs. initialize

bootXxx()initializeXxx()
Quando viene chiamatoUna volta, al primo avvio della classe modelloOgni volta che viene creata un’istanza
Tipo di metodostaticMetodo di istanza
Uso tipicoRegistrare event listener, aggiungere global scopeImpostare valori di default, unire cast

Convenzioni di denominazione

bootXxx()

Definisci un metodo static con prefisso boot seguito dal nome della classe del trait. Eloquent lo invoca una sola volta per ciclo di vita della classe.
namespace App\Models\Concerns;

trait HasSlug
{
    public static function bootHasSlug(): void
    {
        static::creating(function ($model) {
            if (empty($model->slug)) {
                $model->slug = str($model->name)->slug()->toString();
            }
        });
    }
}
Utilizzo del trait in un modello:
use App\Models\Concerns\HasSlug;

class Article extends Model
{
    use HasSlug;
    // bootHasSlug() viene chiamato automaticamente
}

initializeXxx()

Definisci un metodo di istanza con prefisso initialize seguito dal nome della classe del trait. Eloquent lo invoca ogni volta che viene creata una nuova istanza.
namespace App\Models\Concerns;

trait HasDefaultStatus
{
    public function initializeHasDefaultStatus(): void
    {
        $this->attributes['status'] ??= 'draft';
    }
}
Anche l’unione dinamica dei cast è un uso comune:
trait HasMetadata
{
    public function initializeHasMetadata(): void
    {
        $this->mergeCasts([
            'metadata' => 'array',
        ]);
    }
}

Attribute PHP

A partire da Laravel 11, puoi utilizzare gli Attribute PHP invece di affidarti alle convenzioni di denominazione.
AttributeScopo
#[Boot]Marca un metodo statico da eseguire una volta all’avvio della classe
#[Initialize]Marca un metodo di istanza da eseguire ad ogni istanziazione
use Illuminate\Database\Eloquent\Attributes\Boot;
use Illuminate\Database\Eloquent\Attributes\Initialize;

trait HasAuditLog
{
    #[Boot]
    public static function registerAuditListeners(): void
    {
        static::created(function ($model) {
            AuditLog::record('created', $model);
        });

        static::updated(function ($model) {
            AuditLog::record('updated', $model);
        });
    }

    #[Initialize]
    public function setAuditDefaults(): void
    {
        $this->attributes['audit_enabled'] ??= true;
    }
}
L’uso degli Attribute PHP libera i nomi dei metodi dal vincolo del nome del trait. Puoi anche definire più metodi #[Boot] o #[Initialize] all’interno dello stesso trait.

Esempi pratici

Aggiunta automatica di un global scope

trait HasTenant
{
    public static function bootHasTenant(): void
    {
        static::addGlobalScope(new TenantScope);
    }
}

Unione di cast di default

trait HasJsonSettings
{
    public function initializeHasJsonSettings(): void
    {
        $this->mergeCasts([
            'settings' => 'array',
        ]);
    }
}

Archiviazione automatica alla cancellazione

trait Archivable
{
    #[Boot]
    public static function bootArchivable(): void
    {
        static::deleting(function ($model) {
            Archive::store($model->toArray());
        });
    }
}

Esempi nel framework

I trait di Laravel dimostrano chiaramente il pattern:
TraitMetodoCosa fa
SoftDeletesbootSoftDeletes()Registra il global scope SoftDeletingScope
HasUlidsbootHasUlids()Imposta l’ULID nell’evento creating
HasUuidsbootHasUuids()Imposta l’UUID nell’evento creating
Leggere queste implementazioni è un ottimo modo per comprendere il pattern in profondità.

Avvertenze

Pulire i modelli bootati nei test

Poiché boot* viene eseguito una sola volta per classe, i test che modificano il comportamento del modello potrebbero dover reimpostare la cache di boot:
protected function tearDown(): void
{
    Model::clearBootedModels();
    parent::tearDown();
}

Ordine di esecuzione

Quando un modello usa più trait, bootXxx() e initializeXxx() vengono chiamati nell’ordine di risoluzione dei trait di PHP (ordine di dichiarazione). Fai attenzione all’ordine quando i trait dipendono l’uno dall’altro.
PatternCome definirloQuando usarlo
Boot della classestatic bootXxx() o #[Boot]Event listener, global scope
Init dell’istanzainitializeXxx() o #[Initialize]Valori di default, cast dinamici
Implementare bootXxx() e initializeXxx() in un trait ti permette di iniettare comportamenti in qualsiasi modello Eloquent con una singola istruzione use — il pattern di riferimento per gli autori di package.
Ultima modifica il 13 luglio 2026