Laravel - Eloquent - 动态定义的关系

2021-12-26 00:00:00 orm php laravel eloquent

是否可以动态设置模型的关系?例如,我有模型 Page,我想在不实际更改其文件的情况下向其添加关系 banners()?那么是否存在这样的事情:

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 actually changing its file? So does something like this exist:

Page::createRelationship('banners', function(){
    $this->hasMany('banners');
});

或者类似的东西?由于它们无论如何都是使用魔术方法获取的,也许我可以动态添加关系?

Or something similar? As they are fetched using the magic methods anyway, perhaps I can add the relationship dynamically?

谢谢!

推荐答案

我为此添加了一个包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);
});

相关文章