Vue d’ensemble
Chaque fois qu’un modèle Eloquent est instancié, il exécute deux phases : boot (une fois par classe) et initialize (une fois par instance). Lorsque vous définissez des méthodes spécifiques dans un trait, Eloquent les découvre et les appelle automatiquement. Il suffit d’ajouter le trait au modèle.
Laravel lui-même utilise abondamment ce pattern dans des traits tels que SoftDeletes, HasUuids et HasUlids.
boot vs. initialize
| bootXxx() | initializeXxx() |
|---|
| Moment de l’appel | Une seule fois lors du premier boot de la classe du modèle | À chaque création d’instance |
| Type de méthode | static | Méthode d’instance |
| Usage typique | Enregistrer des écouteurs d’événements, ajouter des global scopes | Définir des valeurs d’attributs par défaut, fusionner des casts |
Conventions de nommage
bootXxx()
Définissez une méthode static préfixée par boot suivi du nom de base de la classe du trait. Eloquent l’appelle une seule fois par cycle de vie de la 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();
}
});
}
}
Utilisation du trait dans un modèle :
use App\Models\Concerns\HasSlug;
class Article extends Model
{
use HasSlug;
// bootHasSlug() est appelée automatiquement
}
initializeXxx()
Définissez une méthode d’instance préfixée par initialize suivi du nom de base de la classe du trait. Eloquent l’appelle à chaque création d’une nouvelle instance.
namespace App\Models\Concerns;
trait HasDefaultStatus
{
public function initializeHasDefaultStatus(): void
{
$this->attributes['status'] ??= 'draft';
}
}
La fusion dynamique des casts est un autre usage courant :
trait HasMetadata
{
public function initializeHasMetadata(): void
{
$this->mergeCasts([
'metadata' => 'array',
]);
}
}
PHP Attributes
Depuis Laravel 11, vous pouvez utiliser les PHP Attributes au lieu de vous appuyer sur les conventions de nommage.
| Attribute | Rôle |
|---|
#[Boot] | Marque une méthode statique à exécuter une fois au boot de la classe |
#[Initialize] | Marque une méthode d’instance à exécuter à chaque instanciation |
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’utilisation des PHP Attributes libère les noms de vos méthodes de la contrainte liée au nom du trait. Vous pouvez également définir plusieurs méthodes #[Boot] ou #[Initialize] au sein d’un même trait.
Exemples pratiques
Ajout automatique d’un global scope
trait HasTenant
{
public static function bootHasTenant(): void
{
static::addGlobalScope(new TenantScope);
}
}
Fusion de casts par défaut
trait HasJsonSettings
{
public function initializeHasJsonSettings(): void
{
$this->mergeCasts([
'settings' => 'array',
]);
}
}
Archivage automatique lors de la suppression
trait Archivable
{
#[Boot]
public static function bootArchivable(): void
{
static::deleting(function ($model) {
Archive::store($model->toArray());
});
}
}
Exemples dans le framework
Les propres traits de Laravel illustrent clairement ce pattern :
| Trait | Méthode | Ce qu’il fait |
|---|
SoftDeletes | bootSoftDeletes() | Enregistre le global scope SoftDeletingScope |
HasUlids | bootHasUlids() | Définit un ULID lors de l’événement creating |
HasUuids | bootHasUuids() | Définit un UUID lors de l’événement creating |
Lire ces implémentations est une excellente façon de comprendre le pattern en profondeur.
Points d’attention
Réinitialiser les modèles bootés dans les tests
Puisque boot* ne s’exécute qu’une seule fois par classe, les tests qui modifient le comportement des modèles peuvent nécessiter de réinitialiser le cache de boot :
protected function tearDown(): void
{
Model::clearBootedModels();
parent::tearDown();
}
Ordre d’exécution
Lorsqu’un modèle utilise plusieurs traits, bootXxx() et initializeXxx() sont appelées dans l’ordre de résolution des traits par PHP (ordre de déclaration). Soyez attentif à l’ordre lorsque les traits dépendent les uns des autres.
Résumé
| Pattern | Comment le définir | Quand l’utiliser |
|---|
| Boot de classe | static bootXxx() ou #[Boot] | Écouteurs d’événements, global scopes |
| Initialisation d’instance | initializeXxx() ou #[Initialize] | Valeurs par défaut, casts dynamiques |
Implémenter bootXxx() et initializeXxx() dans un trait vous permet d’injecter du comportement dans n’importe quel modèle Eloquent avec une seule instruction use — le pattern incontournable pour les auteurs de packages.