Search code examples
phplaravellaravel-5

laravel 5 how to add to $with / $appends fields in child model class


I have several models which share some common functionality (due to their polymorphism) which I'd like to pull into a ResourceContentModel class (or even a trait).

The ResourceContentModel class would extend the eloquent Model class and my individual models would then extend ResourceContentModel.

My question is around the model fields like $with, $appends and $touches. If I make use of these for any of the common functionality in ResourceContentModel, then when I redefine them in my child model class, it overwrites the values I've set in my parent class.

Looking for some suggestions for a clean way around this?

For example:

class ResourceContentModel extends Model
{
    protected $with = ['resource']
    protected $appends = ['visibility']

    public function resource()
    {
        return $this->morphOne(Resource::class, 'content');
    }

    public function getVisibilityAttribute()
    {
        return $this->resource->getPermissionScope(Permission::RESOURCE_VIEW);
    }
}

class Photo extends ResourceContentModel
{
    protected $with = ['someRelationship']
    protected $appends = ['some_other_property']

    THESE ARE A PROBLEM AS I LOSE THE VALUES IN ResourceContentModel
}

I'm after a clean way to do this so the child classes aren't overly changed by the fact I've slotted in an extra class in the hierarchy to gather the common code.


Solution

  • No idea if this will work...

    class Photo extends ResourceContentModel
    {
        public function __construct($attributes = [])
        {
            parent::__construct($attributes);
            $this->with = array_merge(['someRelationship'], parent::$this->with);
        }
    }
    

    Or perhaps add a method on ResourceContentModel to access the property.

    class ResourceContentModel extends Model
    {
        public function getParentWith()
        {
            return $this->with;
        }
    }
    

    then

    class Photo extends ResourceContentModel
    {
        public function __construct($attributes = [])
        {
            parent::__construct($attributes);
            $this->with = array_merge(['someRelationship'], parent::getParentWith());
        }
    }
    

    EDIT

    In the constructor of the 3rd snippet,

    $this->with = array_merge(['someRelationship'], parent->getParentWith());

    needed to be

    $this->with = array_merge(['someRelationship'], parent::getParentWith());