是否可以动态设置模型的关系?例如,我有型号Page
,我想添加关系banners()
而不实际更改其文件?那么这样的事情是否存在:Laravel - 雄辩 - 动态定义的关系
Page::createRelationship('banners', function(){
$this->hasMany('banners');
});
或者类似的东西?因为无论如何都使用魔术方法获取它们,也许我可以动态地添加关系?
谢谢!
是否可以动态设置模型的关系?例如,我有型号Page
,我想添加关系banners()
而不实际更改其文件?那么这样的事情是否存在:Laravel - 雄辩 - 动态定义的关系
Page::createRelationship('banners', function(){
$this->hasMany('banners');
});
或者类似的东西?因为无论如何都使用魔术方法获取它们,也许我可以动态地添加关系?
谢谢!
你必须记住一些事情,Eloquent关系是关系数据库关系(即MySQL)的模型。 所以,我有两种方法。
好
如果要实现与数据库中的索引和foreing键全功能的口才关系,你可能要动态地改变SQL表。
例如,假设您创建了所有模型并且不想动态创建它们,只需更改Page表格,添加一个名为“banner_id”的新字段,将其索引并引用“banner_id”在横幅桌上的领域。
然后,您必须记下并支持您将使用的RDBMS。之后,您可能需要包含对迁移的支持。如果是这种情况,您可以在数据库中存储这些表进行进一步回滚的更改。
现在,对于Eloquent支持部分,您可以查看Eloquent Model Class。
看出,对于每一种关系,你有一个subyacent模型(所有可以找到here,这实际上是你在relatioship方法返回:
public function hasMany($related, $foreignKey = null, $localKey = null)
{
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
$localKey = $localKey ?: $this->getKeyName();
return new HasMany($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
}
所以,你必须定义一个方法在你的模型中接受关系类型和模型,创建一个新的HasMany(如果hasMany是期望的关系)实例,然后返回它。
这有点复杂,所以你可以使用:
The easy
您可以创建一个中间模型(即, PageRelationship),它存储Page和其他模型之间的所有关系。一个可能的表格模式可能是:
+-------------+---------+------------------+-------------+
| relation_id | page_id | foreign_model_id | model_class |
+-------------+---------+------------------+-------------+
| 1 | 2 | 225 | Banner |
| 2 | 2 | 223 | Banner |
| 3 | 2 | 12 | Button |
+-------------+---------+------------------+-------------+
然后,您可以检索给定页面的所有动态相关模型。这里的问题在于,模型和页面之间实际上并没有任何真正的RDBMS关系,因此您可能必须针对加载相关模型进行多重查询,更糟糕的是,您必须自己管理数据库一致性(即,删除或更新“225”横幅也应删除或更新page_relationship_table中的行)。反向关系也会令人头痛。
结论
如果项目很大,这取决于这一点,你不能让那个通过继承来实现其他车型的典范左右,你应该使用的好办法。否则,您应该重新考虑应用程序设计,然后决定是否选择第二种方法。
感谢您的广泛答复。我可以看到如何使用任何一种解决方案,但是如果我没有弄错,两者都需要编辑“Page”模型类。由于我的系统是完全模块化的,因此我试图找到扩展其他模块的模块方式,而不会使模型本身过度复杂化。 – Giedrius
您必须对其进行修改,使其能够处理动态关系功能,因为它不是本地实施的,但您不必稍后再进行更改。模块化系统的正确方法是具有继承模型结构,所以Banner模型扩展了PageElement模型,并建立了Page和PageElement之间的关系。无论如何,使模块化的东西[将复杂化你的模型](http://stackoverflow.com/questions/23973850/model-inheritance-in-laravel)。 – vpedrosa
我将拥有自己的Model类的扩展,它可以被所有模型扩展以获得自定义功能,或者可以将动态关系功能添加到laravel框架中并提交拉取请求,以防更多人觉得有用。一旦我找到一个明确的解决方案,将会发布一个答案。 – Giedrius
您可以使用macro
呼吁你这样的动态关系:
你应该在你的服务提供商的引导方法编写代码。
\Illuminate\Database\Eloquent\Builder::macro('yourRelation', function() {
return $this->getModel()->belongsTo('class');
});
使用多态的关系和特点,将完成你想要看看,在laravel单证 –
如果我没看错你还是要定义这些原'Page'模式是什么?我正在寻找一种方法来添加这种关系,而无需编辑文件 – Giedrius
我可以看到'Model'类有一个'setRelation'方法,但它不是静态的,只能在实例上调用。有什么类似的我可以使用,所以它会自动设置所有创建的实例的关系? – Giedrius