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

> Ein tiefer Einblick in den Trait-Auto-Boot-Mechanismus von Eloquent. Lernen Sie die Namenskonventionen bootXxx() und initializeXxx() sowie die Verwendung von PHP Attributes zur expliziten Registrierung – ein essenzielles Muster für die Paketentwicklung.

## Überblick

Jedes Mal, wenn ein Eloquent-Modell instanziiert wird, durchläuft es zwei Phasen: **boot** (einmal pro Klasse) und **initialize** (einmal pro Instanz). Wenn Sie bestimmte Methoden in einem Trait definieren, erkennt Eloquent diese automatisch und ruft sie auf. Es genügt, den Trait dem Modell hinzuzufügen.

Laravel selbst nutzt dieses Muster ausgiebig in Traits wie `SoftDeletes`, `HasUuids` und `HasUlids`.

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

    App->>Model: new Post() oder Post::find()
    Model->>Model: bootIfNotBooted()
    Model->>Trait: bootXxx() (einmal pro Klasse)
    Model->>Model: initializeTraits()
    Model->>Trait: initializeXxx() (pro Instanz)
    Model-->>App: Modellinstanz
```

***

## boot vs. initialize

|                         | `bootXxx()`                                            | `initializeXxx()`                                   |
| ----------------------- | ------------------------------------------------------ | --------------------------------------------------- |
| **Wann aufgerufen**     | Einmal, wenn die Modellklasse erstmals bootet          | Bei jeder Instanzerstellung                         |
| **Methodentyp**         | `static`                                               | Instanzmethode                                      |
| **Typische Verwendung** | Event-Listener registrieren, globale Scopes hinzufügen | Standard-Attributwerte setzen, Casts zusammenführen |

***

## Namenskonventionen

### bootXxx()

Definieren Sie eine **`static`** Methode mit dem Präfix `boot`, gefolgt vom Klassenbasisnamen des Traits. Eloquent ruft sie einmal pro Klassen-Lebenszyklus auf.

```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();
            }
        });
    }
}
```

Verwendung des Traits in einem Modell:

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

class Article extends Model
{
    use HasSlug;
    // bootHasSlug() wird automatisch aufgerufen
}
```

### initializeXxx()

Definieren Sie eine Instanzmethode mit dem Präfix `initialize`, gefolgt vom Klassenbasisnamen des Traits. Eloquent ruft sie bei jeder Erstellung einer neuen Instanz auf.

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

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

Das dynamische Zusammenführen von Casts ist ein weiterer häufiger Anwendungsfall:

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

***

## PHP Attributes

Seit Laravel 11 können Sie anstelle von Namenskonventionen PHP Attributes verwenden.

| Attribute       | Zweck                                                                         |
| --------------- | ----------------------------------------------------------------------------- |
| `#[Boot]`       | Markiert eine statische Methode, die einmal beim Klassen-Boot ausgeführt wird |
| `#[Initialize]` | Markiert eine Instanzmethode, die bei jeder Instanziierung ausgeführt wird    |

```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>
  Durch die Verwendung von PHP Attributes werden Ihre Methodennamen von der Einschränkung des Trait-Namens befreit. Sie können außerdem mehrere `#[Boot]`- oder `#[Initialize]`-Methoden innerhalb desselben Traits definieren.
</Info>

***

## Praktische Beispiele

### Globalen Scope automatisch hinzufügen

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

### Standard-Casts zusammenführen

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

### Automatisches Archivieren beim Löschen

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

***

## Beispiele aus dem Framework

Die eigenen Traits von Laravel veranschaulichen das Muster deutlich:

| Trait         | Methode             | Was sie tut                                  |
| ------------- | ------------------- | -------------------------------------------- |
| `SoftDeletes` | `bootSoftDeletes()` | Registriert den globalen `SoftDeletingScope` |
| `HasUlids`    | `bootHasUlids()`    | Setzt die ULID beim `creating`-Event         |
| `HasUuids`    | `bootHasUuids()`    | Setzt die UUID beim `creating`-Event         |

Diese Implementierungen zu lesen ist ein guter Weg, das Muster tiefergehend zu verstehen.

***

## Hinweise

### Booted Models in Tests zurücksetzen

Da `boot*` nur einmal pro Klasse ausgeführt wird, müssen Tests, die das Modellverhalten ändern, gegebenenfalls den Boot-Cache zurücksetzen:

```php theme={null}
protected function tearDown(): void
{
    Model::clearBootedModels();
    parent::tearDown();
}
```

### Ausführungsreihenfolge

Wenn ein Modell mehrere Traits verwendet, werden `bootXxx()` und `initializeXxx()` in der PHP-Trait-Auflösungsreihenfolge (Deklarationsreihenfolge) aufgerufen. Achten Sie auf die Reihenfolge, wenn Traits voneinander abhängen.

***

## Zusammenfassung

| Muster                  | Wie definieren                         | Wann verwenden                  |
| ----------------------- | -------------------------------------- | ------------------------------- |
| Klassen-Boot            | `static bootXxx()` oder `#[Boot]`      | Event-Listener, globale Scopes  |
| Instanz-Initialisierung | `initializeXxx()` oder `#[Initialize]` | Standardwerte, dynamische Casts |

Wenn Sie `bootXxx()` und `initializeXxx()` in einem Trait implementieren, können Sie mit einer einzigen `use`-Anweisung Verhalten in jedes Eloquent-Modell einfügen – das bevorzugte Muster für Paketautoren.


## Related topics

- [Conditionable-Trait](/de/advanced/conditionable.md)
- [Dumpable-Trait](/de/advanced/dumpable.md)
- [Eloquent-Factories](/de/eloquent-factories.md)
- [ForwardsCalls-Trait](/de/advanced/forwards-calls.md)
- [Eloquent-Scopes](/de/advanced/eloquent-scopes.md)
