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

> A deep dive into Eloquent's trait auto-boot mechanism. Learn the bootXxx() and initializeXxx() naming conventions and how to use PHP Attributes for explicit registration — an essential pattern for package development.

## Overview

Every time an Eloquent model is instantiated it runs two phases: **boot** (once per class) and **initialize** (once per instance). When you define specific methods in a trait, Eloquent automatically discovers and calls them. Adding the trait to a model is all that's needed.

Laravel itself uses this pattern extensively in traits like `SoftDeletes`, `HasUuids`, and `HasUlids`.

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

    App->>Model: new Post() or Post::find()
    Model->>Model: bootIfNotBooted()
    Model->>Trait: bootXxx() (once per class)
    Model->>Model: initializeTraits()
    Model->>Trait: initializeXxx() (per instance)
    Model-->>App: model instance
```

***

## boot vs. initialize

|                 | `bootXxx()`                                 | `initializeXxx()`                         |
| --------------- | ------------------------------------------- | ----------------------------------------- |
| **When called** | Once when the model class first boots       | Every time an instance is created         |
| **Method type** | `static`                                    | Instance method                           |
| **Typical use** | Register event listeners, add global scopes | Set default attribute values, merge casts |

***

## Naming Conventions

### bootXxx()

Define a **`static`** method prefixed with `boot` followed by the trait's class basename. Eloquent calls it once per class lifecycle.

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

Using the trait in a model:

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

class Article extends Model
{
    use HasSlug;
    // bootHasSlug() is called automatically
}
```

### initializeXxx()

Define an instance method prefixed with `initialize` followed by the trait's class basename. Eloquent calls it every time a new instance is created.

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

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

Dynamically merging casts is another common use:

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

***

## PHP Attributes

Since Laravel 11, you can use PHP Attributes instead of relying on naming conventions.

| Attribute       | Purpose                                               |
| --------------- | ----------------------------------------------------- |
| `#[Boot]`       | Mark a static method to run once when the class boots |
| `#[Initialize]` | Mark an instance method to run on every instantiation |

```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>
  Using PHP Attributes frees your method names from the trait-name constraint. You can also define multiple `#[Boot]` or `#[Initialize]` methods within the same trait.
</Info>

***

## Practical Examples

### Adding a Global Scope Automatically

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

### Merging Default Casts

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

### Auto-archiving on Delete

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

***

## Examples in the Framework

Laravel's own traits demonstrate the pattern clearly:

| Trait         | Method              | What it does                                   |
| ------------- | ------------------- | ---------------------------------------------- |
| `SoftDeletes` | `bootSoftDeletes()` | Registers the `SoftDeletingScope` global scope |
| `HasUlids`    | `bootHasUlids()`    | Sets ULID on the `creating` event              |
| `HasUuids`    | `bootHasUuids()`    | Sets UUID on the `creating` event              |

Reading these implementations is a great way to understand the pattern in depth.

***

## Caveats

### Clearing Booted Models in Tests

Because `boot*` runs only once per class, tests that alter model behavior may need to reset the boot cache:

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

### Execution Order

When a model uses multiple traits, `bootXxx()` and `initializeXxx()` are called in PHP's trait resolution order (declaration order). Be mindful of ordering when traits depend on each other.

***

## Summary

| Pattern       | How to define                        | When to use                    |
| ------------- | ------------------------------------ | ------------------------------ |
| Class boot    | `static bootXxx()` or `#[Boot]`      | Event listeners, global scopes |
| Instance init | `initializeXxx()` or `#[Initialize]` | Default values, dynamic casts  |

Implementing `bootXxx()` and `initializeXxx()` in a trait lets you inject behavior into any Eloquent model with a single `use` statement — the go-to pattern for package authors.


## Related topics

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