Let's say you want to use multiple traits in your models to reuse common code such as applying UUIDs and settings global query scopes like this:
use HasUuid; use HasTenant;
Each of these traits has a boot method:
HasUuid :
trait HasUuid { public function getIncrementing(): bool { return false; } public function getKeyType(): string { return 'string'; } public static function boot() { static::creating(function (Model $model) { // Set attribute for new model's primary key (ID) to an uuid. $model->setAttribute($model->getKeyName(), Str::uuid()->toString()); }); } }
HasTenant:
trait HasTenant { public static function boot() { if (auth()->check()) { $tenantId = auth()->user()->tenant_id; //assign when creating a record static::creating(function ($query) use ($tenantId) { $query->tenant_id = $tenantId; }); //apply condition to all queries static::addGlobalScope('tenant', function (Builder $builder) use ($tenantId) { $builder->where('tenant_id', $tenantId); }); } } }
trying to run this will trigger an error:
Trait method App\Models\Traits\HasTenant::boot has not been applied as App\Models\User::boot, because of collision with App\Models\Traits\HasUuid::boot
This is because both traits are using a boot method, to solve this Laravel supports a bootTraitName for example HasTenant becomes bootHasTenant
Change both traits to use the bootTraitName like this:
trait HasUuid { public static function bootHasUuid() {
and
trait HasTenant { public static function bootHasTenant() {
Now they can be used together in a single model without causing any errors.
Laravel also supports initializeTraitName which can look like:
protected function initializeHasToken() { $this->token = Str::random(100); }
Top comments (0)