Laravel - Eloquent - 动态定义的关系

Gie*_*ius 6 php orm laravel eloquent

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

Page::createRelationship('banners', function(){
    $this->hasMany('banners');
});
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Roc*_*cky 15

我为这个i-rocky/eloquent-dynamic-relation添加了一个包

如果有人仍在寻找解决方案,这里有一个。如果您认为这是个坏主意,请告诉我。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的模型中添加此特征,如下所示

class MyModel extends Model {
    use HasDynamicRelation;
}
Run Code Online (Sandbox Code Playgroud)

现在您可以使用以下方法添加新关系

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


Mat*_*ika 4

从 Laravel 7 开始,正式支持动态关系。您可以使用 Model::resolveRelationUsing() 方法。

https://laravel.com/docs/7.x/eloquent-relationships#dynamic-relationships