1

I am using Laravel 7 and at the moment I am trying to centralize some code by using PHP traits. However, I want to have traits which e.g. also add values to the protected $attributes variable or the protected $with variable.

Why I want that? Because I want to have code reuse and not to tell every Laravel model where I use my trait to also load the relationship and add the attributes to my model. That would be quite redundant...

I already figured out a way to add values to the protected $attributes variable. However, how can I add comments to my protected $with variable?

This is the code to add values to the protected $attributes variable:

    /* Add attributes to model $appends */
    protected function getArrayableAppends()
    {
        $this->appends = array_unique(array_merge($this->appends, ['publishedComments']));

        return parent::getArrayableAppends();
    }

Kind regards

Jan
  • 1,180
  • 3
  • 23
  • 60

1 Answers1

1

Traits used by Model's can be "booted" and "initialized". Booting is a static method of adjusting the behavior usually. Initializing is done on every new instance of the model, which is what you would want to be using:

protected function initializeYourTraitName()
{
    // do what you need to merge into $this->appends
    // do what you need to merge in new values to $this->with
}

If you check the constructor of Illuminate\Database\Eloquent\Model you will see the call to initializeTraits.

You would need to also define a method for booting your trait, which would make the model aware of your "initialize" method that should be called on every new instance of the model.

protected static function bootYourTraitName()
{
    $class = static::class;
    $method = "initializeYourTraitName";

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

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

These are methods of your trait.

The YourTraitName part you have to change to the name of your trait.

lagbox
  • 48,571
  • 8
  • 72
  • 83
  • So, it would be `$this->appends = array_unique(array_merge($this->appends, ['publishedComments']));` and `$this->with = array_unique(array_merge($this->with, ['comments']));` inside this function? Where do I place this function? In my model or my trait? – Jan Sep 22 '20 at 21:06
  • `appends` is not adding to the attributes array, appends is only for serializing the model – lagbox Sep 22 '20 at 21:07
  • So, it would be `attributes`. But where do I boot my trait how do I call this functino? – Jan Sep 22 '20 at 21:10
  • apparently you don't want to add to the `attributes` array, you want to add an 'accessor' which would go to `appends` ... you do not call either of these methods, the model does this – lagbox Sep 22 '20 at 21:12
  • 1
    Thank you, I will try it tomorrow. – Jan Sep 22 '20 at 21:14