我在Laravel模型上有一个雄辩的关系,它是动态的 - 也就是说,特定数据库字段的值决定了哪个模型将被加载 . 当我第一次实例化模型实例然后引用关系时,我能够很好地加载这种关系,但是当我急切地加载这种关系时它不起作用 .
具体来说,我有一个 Product
模型 . 该产品可能是也可能不是其他产品的父母 . 如果产品的 parent_id
设置为 0
,则该产品被视为父产品(无论是否有子产品) . 如果 parent_id
设置为其他产品的ID,则该产品是子产品 . 我需要能够访问 Product::with('parent')
并知道 parent
关系将返回其自身(是,重复数据)或不同的产品(如果它是孩子) .
这是我到目前为止的关系:
public function parent()
{
if ($this->parent_id > 0) {
return $this->belongsTo('App\Product', 'parent_id', 'id');
} else {
return $this->belongsTo('App\Product', 'id', 'id');
}
}
当我急切地加载时, $this->parent_id
总是未定义的,因此即使它实际上是父产品,这种关系也只会自行返回 .
在关系被急切加载之前,有没有办法访问模型的属性?在我返回关系之前,我考虑过在单独的查询中工作,但我意识到我甚至没有运行该查询的id .1121236_的id .
如果不可能,还有哪些其他方法可以解决这类问题?这似乎不能通过传统的多态关系来解决 . 我只有两个可能的想法:
-
为我动态确定外键的
belongsTo
关系添加某种约束 . -
创建我自己的自定义关系,该关系使用基于不同数据库字段的外键 .
老实说,我不知道如何实现其中任何一个 . 我是以正确的方式来做这件事的吗?有什么我可以忽略的吗?
在考虑了这个之后,我认为最简单的问题是: is there any way to dynamically select a foreign key for a relationship inside the relation itself at runtime ?当我调用关系时,我的用例不允许我使用急切的加载约束 - 约束需要应用于关系本身 .
1 回答
由于渴望加载的方式起作用,因此没有任何东西可以用来运行SQL来完成你正在寻找的东西 .
当你执行
Product::with('parent')->get()
时,它会运行两个查询 .首先,它运行查询以获取所有产品:
接下来,它运行一个查询来获取渴望加载的父项:
参数数量(
?
)对应于第一个查询的结果数 . 一旦检索到第二组模型,match()
函数用于将对象相互关联 .为了做你想做的事,你将不得不创建一个新的关系并覆盖
match()
方法 . 这将处理急切的加载方面 . 此外,您还需要覆盖addConstraints
方法来处理延迟加载方面 .首先,创建一个自定义关系类:
创建自定义关系类后,需要更新模型以使用此自定义关系 . 在模型上创建一个将使用新的
CustomBelongsTo
关系的新方法,并更新parent()
关系方法以使用此新方法,而不是基本belongsTo()
方法 .公平警告,这些都没有经过测试 .