Laravel - 计算自我引用关系

时间:2018-01-28 13:26:06

标签: php laravel

好的,我正在开发一个laravel 5.5项目。

我们有一个用户表,在这个用户表中我们有一个父字段。 父级拒绝此对象的父关系。

因此每个用户可以拥有1个父级,但用户可以拥有多个子级。

    public function parent()
{
    return $this->belongsTo(User::class, 'parent_id', 'id');
}

public function children()
{
    return $this->hasMany(User::class, 'parent_id', 'id');
}

我想要达到的目标是什么。我需要计算5个级别的用户拥有多少个孩子。

所以我想要这样的东西:

等级1:585 等级2:1539 等级3:3294 等级4:4949 等级5:15939

无需加载实际对象,因为它会破坏页面性能。

我如何用laravel实现这一目标? 这是我尝试的内容,但是它会将所有子项加载到集合中。

  $sum = User::with('parent')->where('id','=', $user->id)->get();

有人可以帮我解决这个问题吗?

编辑:

更具体一点:

假设用户A是B和C的父母

B是D,E,F的父母 C没有孩子。

正确的输出应该是:

等级1:2 等级2:3(因为C没有孩子)

希望能让它更清晰

2 个答案:

答案 0 :(得分:0)

如果将新属性附加到模型

,该怎么办?
class User extends Model{
   protected $append = ['children_count'];

   public function getChildrenCountAttribute()
   {
       return $this->children()->count();
   }
}

现在,您可以获得一个没有孩子的用户的数量

$user->children_count;

答案 1 :(得分:0)

很抱歉回答一个老问题,但是我想自己解决这个问题,所以我想出了这个解决方案,效果似乎很好,也许您可​​以用它来解决您的问题。

通过急于加载子级,我们避免了在计数循环期间进行多次查询,总是急于加载子级的缺点是,如果它们之间的关系很长很深,可能会返回大量数据,请对其进行测试,以确保其性能足以满足您的使用需求情况。

通过在数据库上使用正确的索引并确保数据库结构良好,可以提高某些性能,因此这绝不应该太慢,因为它是与获取单个行相同的查询中的单个查询/完成

避免急于加载父级和子级,因为它们是自引用的,会导致无限循环

通过添加急切的负载,我们可以遍历关系并返回子代总数,请参见下面的代码。

class User extends Model{
   protected $append = ['children_count'];
   protected $with = ['children']; //Eager load the relationship

   public function parent()
   {
    return $this->belongsTo(User::class, 'parent_id', 'id');
   }

   public function children()
   {
    return $this->hasMany(User::class, 'parent_id', 'id');
   } 

   public function getChildrenCountAttribute()
   {
       $count = $this->children->count(); //This specific models count

       //Loop through the already loaded children and get their count
       foreach($this->children as $child){
          $count += $child->children->count(); //Sum up the count
       }

       return $count; //Return the result
   }
}