Laravel use multiple boot in traits

David CarrDavid Carr
2 min read

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);
}
0
Subscribe to my newsletter

Read articles from David Carr directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

David Carr
David Carr

Blogger at http://dcblog.dev.