Laravel – Different between Model trait boot & initialization

Trace back to Model we have

    protected static function bootTraits()
    {
        $class = static::class;

        $booted = [];

        static::$traitInitializers[$class] = [];

        foreach (class_uses_recursive($class) as $trait) {
            $method = 'boot'.class_basename($trait);

            if (method_exists($class, $method) && ! in_array($method, $booted)) {
                forward_static_call([$class, $method]);

                $booted[] = $method;
            }

            if (method_exists($class, $method = 'initialize'.class_basename($trait))) {
                static::$traitInitializers[$class][] = $method;

                static::$traitInitializers[$class] = array_unique(
                    static::$traitInitializers[$class]
                );
            }
        }
    }

Theo như code trên có thể thấy

  • boot sẽ call đến static method. Hay nói cách khác sẽ tác động tới mọi instances của Model này
  • trong khi đó `initialize thì ngược lại. Chỉ tác động tới instance hiện tại.

1 ví dụ thực tế

trait HasSlug
{
    public function initializeHasSystem()
    {
        $this->mergeCasts([
            'slug' => 'string'
        ]);

        $this->mergeFillable([
            'slug'
        ]);
    }

    public static function bootHasSlug()
    {
        static::creating(function ($model) {
            $model->{$model->getSlugName()} = Str::slug($model->name);
        });

        static::updating(function ($model) {
            $model->{$model->getSlugName()} = Str::slug($model->name);
        });
    }

    public function scopeSlug($query, $uuid)
    {
        return $query->where($this->getSlugName(), $uuid);
    }

    public function getSlugName()
    {
        return property_exists($this, 'slug') ? $this->slug : 'slug';
    }
}