Laravel - Eloquent - Dynamically defined relationship

前端 未结 4 717
广开言路
广开言路 2021-01-13 09:24

Is it possible to set a model\'s relationship dynamically? For example, I have model Page, and I want to add relationship banners() to it without a

4条回答
  •  别那么骄傲
    2021-01-13 09:41

    I've added a package for this i-rocky/eloquent-dynamic-relation

    In case anyone still looking for a solution , here is one. If you think it's a bad idea, let me know.

    trait HasDynamicRelation
    {
        /**
         * Store the relations
         *
         * @var array
         */
        private static $dynamic_relations = [];
    
        /**
         * Add a new relation
         *
         * @param $name
         * @param $closure
         */
        public static function addDynamicRelation($name, $closure)
        {
            static::$dynamic_relations[$name] = $closure;
        }
    
        /**
         * Determine if a relation exists in dynamic relationships list
         *
         * @param $name
         *
         * @return bool
         */
        public static function hasDynamicRelation($name)
        {
            return array_key_exists($name, static::$dynamic_relations);
        }
    
        /**
         * If the key exists in relations then
         * return call to relation or else
         * return the call to the parent
         *
         * @param $name
         *
         * @return mixed
         */
        public function __get($name)
        {
            if (static::hasDynamicRelation($name)) {
                // check the cache first
                if ($this->relationLoaded($name)) {
                    return $this->relations[$name];
                }
    
                // load the relationship
                return $this->getRelationshipFromMethod($name);
            }
    
            return parent::__get($name);
        }
    
        /**
         * If the method exists in relations then
         * return the relation or else
         * return the call to the parent
         *
         * @param $name
         * @param $arguments
         *
         * @return mixed
         */
        public function __call($name, $arguments)
        {
            if (static::hasDynamicRelation($name)) {
                return call_user_func(static::$dynamic_relations[$name], $this);
            }
    
            return parent::__call($name, $arguments);
        }
    }
    

    Add this trait in your model as following

    class MyModel extends Model {
        use HasDynamicRelation;
    }
    

    Now you can use the following method to add new relationships

    MyModel::addDynamicRelation('some_relation', function(MyModel $model) {
        return $model->hasMany(SomeRelatedModel::class);
    });
    

提交回复
热议问题