> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Eloquent Bootable Traits

> Un approfondimento sul meccanismo di auto-boot dei trait di Eloquent. Impara le convenzioni di denominazione bootXxx() e initializeXxx() e come usare gli Attribute PHP per la registrazione esplicita — un pattern essenziale per lo sviluppo di package.

## 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`.

```mermaid theme={null}
sequenceDiagram
    participant App as Applicazione
    participant Model as Eloquent Model
    participant Trait as Trait

    App->>Model: new Post() oppure Post::find()
    Model->>Model: bootIfNotBooted()
    Model->>Trait: bootXxx() (una volta per classe)
    Model->>Model: initializeTraits()
    Model->>Trait: initializeXxx() (per istanza)
    Model-->>App: istanza del modello
```

***

## boot vs. initialize

|                           | `bootXxx()`                                        | `initializeXxx()`                       |
| ------------------------- | -------------------------------------------------- | --------------------------------------- |
| **Quando viene chiamato** | Una volta, al primo avvio della classe modello     | Ogni volta che viene creata un'istanza  |
| **Tipo di metodo**        | `static`                                           | Metodo di istanza                       |
| **Uso tipico**            | Registrare event listener, aggiungere global scope | Impostare 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.

```php theme={null}
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:

```php theme={null}
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.

```php theme={null}
namespace App\Models\Concerns;

trait HasDefaultStatus
{
    public function initializeHasDefaultStatus(): void
    {
        $this->attributes['status'] ??= 'draft';
    }
}
```

Anche l'unione dinamica dei cast è un uso comune:

```php theme={null}
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.

| Attribute       | Scopo                                                                |
| --------------- | -------------------------------------------------------------------- |
| `#[Boot]`       | Marca un metodo statico da eseguire una volta all'avvio della classe |
| `#[Initialize]` | Marca un metodo di istanza da eseguire ad ogni istanziazione         |

```php theme={null}
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;
    }
}
```

<Info>
  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.
</Info>

***

## Esempi pratici

### Aggiunta automatica di un global scope

```php theme={null}
trait HasTenant
{
    public static function bootHasTenant(): void
    {
        static::addGlobalScope(new TenantScope);
    }
}
```

### Unione di cast di default

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

### Archiviazione automatica alla cancellazione

```php theme={null}
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:

| Trait         | Metodo              | Cosa fa                                      |
| ------------- | ------------------- | -------------------------------------------- |
| `SoftDeletes` | `bootSoftDeletes()` | Registra il global scope `SoftDeletingScope` |
| `HasUlids`    | `bootHasUlids()`    | Imposta l'ULID nell'evento `creating`        |
| `HasUuids`    | `bootHasUuids()`    | 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:

```php theme={null}
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.

***

## Riepilogo

| Pattern           | Come definirlo                      | Quando usarlo                    |
| ----------------- | ----------------------------------- | -------------------------------- |
| Boot della classe | `static bootXxx()` o `#[Boot]`      | Event listener, global scope     |
| Init dell'istanza | `initializeXxx()` 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.


## Related topics

- [Trait Dumpable](/it/advanced/dumpable.md)
- [Trait Conditionable](/it/advanced/conditionable.md)
- [Eloquent Factory](/it/eloquent-factories.md)
- [Trait ForwardsCalls](/it/advanced/forwards-calls.md)
- [Scope di Eloquent](/it/advanced/eloquent-scopes.md)
