访问 Parent 关系 Laravel
Accessing Parent relations Laravel
我有一种情况需要遍历模型关系(一对多)并调用 children 上的函数。即
$parent = ParentClass::find(1)
$children = $parent->children;
foreach($children as $child)
{
$child->function();
}
child 中的函数需要访问 parent 模型中的字段。即
public function function()
{
if($this->parent->attribute)
return "True!";
return "False";
}
如上执行此操作,最终出现 N+1 查询问题。每个 child 最终执行 "SELECT * FROM parents WHERE id = 1".
关于如何解决这个问题,我有 3 个想法,尽管其中两个感觉很糟糕,最后一个对我来说似乎不太好,所以我想问有没有比这个更好的解决方案我考虑了什么?
解决方案 1:急切地将 parent 加载到 child 模型上。即
...
$children = $parent->children;
$children->load('parent');
foreach($children as $child)
...
我认为很明显为什么这会很糟糕,将 parent 模型存储在内存中 N+1 次将是一个巨大的内存消耗。
解决方案 2:将 parent 作为参数传递给 child,即
...
foreach($children as $child)
{
$child->function($parent);
}
...
避免了1的内存问题,但还是觉得丑。我认为 child 应该知道它是 parent,而不需要通过方法 args 告诉它。
解决方案 3:将 remember() 添加到 child 的 parent 关系中,即
public function parent()
{
return $this->hasOne('Parent')->remember(1);
}
由于所有 children 都具有相同的 parent,这将缓存查询,并避免为每个 child 调用它。这似乎是这 3 种解决方案中最好的,但我不喜欢将其作为关系中强制性要求的想法。
有没有我没有考虑的更好的方法?也许是包含记忆功能的更好地方?
谢谢你,-Wally
如果您定义了反向关系,您可以执行以下操作:
$parent = ParentClass::find(1);
foreach ($parent->children as $child) {
$requiredParentAttr = $parent->attr;
$child->function($requiredParentAttr);
// whatever else
}
我想我找到了一个令我满意的解决方案。我仍然感觉不到 "Eloquent",但我认为可能没有更好的解决方案,(尽管随时证明我错了。)
foreach($children as $child)
{
$child->parent = $parent;
$child->function();
}
既然我们已经有了父对象,就把父对象赋值给每个子对象作为引用。这避免了任何内存问题。这甚至比 remember() 选项更好,因为它从不为父级执行第二次查询。这使方法签名保持干净和合乎逻辑。
我有一种情况需要遍历模型关系(一对多)并调用 children 上的函数。即
$parent = ParentClass::find(1)
$children = $parent->children;
foreach($children as $child)
{
$child->function();
}
child 中的函数需要访问 parent 模型中的字段。即
public function function()
{
if($this->parent->attribute)
return "True!";
return "False";
}
如上执行此操作,最终出现 N+1 查询问题。每个 child 最终执行 "SELECT * FROM parents WHERE id = 1".
关于如何解决这个问题,我有 3 个想法,尽管其中两个感觉很糟糕,最后一个对我来说似乎不太好,所以我想问有没有比这个更好的解决方案我考虑了什么?
解决方案 1:急切地将 parent 加载到 child 模型上。即
...
$children = $parent->children;
$children->load('parent');
foreach($children as $child)
...
我认为很明显为什么这会很糟糕,将 parent 模型存储在内存中 N+1 次将是一个巨大的内存消耗。
解决方案 2:将 parent 作为参数传递给 child,即
...
foreach($children as $child)
{
$child->function($parent);
}
...
避免了1的内存问题,但还是觉得丑。我认为 child 应该知道它是 parent,而不需要通过方法 args 告诉它。
解决方案 3:将 remember() 添加到 child 的 parent 关系中,即
public function parent()
{
return $this->hasOne('Parent')->remember(1);
}
由于所有 children 都具有相同的 parent,这将缓存查询,并避免为每个 child 调用它。这似乎是这 3 种解决方案中最好的,但我不喜欢将其作为关系中强制性要求的想法。
有没有我没有考虑的更好的方法?也许是包含记忆功能的更好地方?
谢谢你,-Wally
如果您定义了反向关系,您可以执行以下操作:
$parent = ParentClass::find(1);
foreach ($parent->children as $child) {
$requiredParentAttr = $parent->attr;
$child->function($requiredParentAttr);
// whatever else
}
我想我找到了一个令我满意的解决方案。我仍然感觉不到 "Eloquent",但我认为可能没有更好的解决方案,(尽管随时证明我错了。)
foreach($children as $child)
{
$child->parent = $parent;
$child->function();
}
既然我们已经有了父对象,就把父对象赋值给每个子对象作为引用。这避免了任何内存问题。这甚至比 remember() 选项更好,因为它从不为父级执行第二次查询。这使方法签名保持干净和合乎逻辑。