Search code examples
phplaraveleloquentmodeltraits

How to configure Laravel model attributes in a trait?


I have a trait called Multilingual which uses the model its lang and translation_of attributes (also see https://stackoverflow.com/a/7299777/1453912) to provide multiple translations of an entity.

Now I want to hide the translation_of field from the model when $model->toArray() is called, which is - most easily - done through adding it to the $hidden attribute. Like this:

class Model {
    use Multilingual;

    protected $hidden = ['translation_of'];
}

But to keep the original model clean, I want to add the hidden field via the used trait.

I have tried:

  1. Adding protected $hidden = ['translation_of']; to the trait, which is not allowed: Undefined: trait declaration of property 'hidden' is incompatible with previous declaration

    And also not very extensible (It will be overridden by the $hidden property of the class, I think..)

  2. Adding a boot method to the trait:

    static function bootMultilingual() {
        static::$hidden[] = 'translation_of';
    }
    

    Which (as I suspected) is also not allowed, because of the scope.

Any ideas for a clean way to do this?

Please help!


NOTE: To keep it dynamic, I figured it can be done in two ways:

  1. Internally: $this->hidden[] = 'translation_of';
  2. Externally: $model->setHidden(array_merge($model->getHidden(), ['translation_of']));

Solution

  • You could override the method where $this->hidden is actually used. And that's getArrayableItems

    trait Multilingual {
    
        protected function getArrayableItems(array $values)
        {
            if(!in_array('translation_of', $this->hidden)){
                $this->hidden[] = 'translation_of';
            }
            return parent::getArrayableItems($values);
        }
    }