【问题标题】:Eloquent Relationship Count雄辩的关系计数
【发布时间】:2014-09-24 20:58:03
【问题描述】:

我对 Laravel 4 和 Elqouent 有疑问。我的模型实现了以下关系:

用户belongsToMany角色
角色 belongsToMany 用户

我想查询角色并想获得与他们相关的用户的数量。

当我执行以下操作时,我遇到了 N+1 问题:

$role = Role::has('users')->get()->each(function($role) {
    $role->user_count = $role->users()->count();
});

有什么我没有想到的吗?

【问题讨论】:

  • 结合 with() 和 has()。仅供参考,如果您只使用 with() 您将获得包含没有角色的用户的结果。 laravel.com/docs/eloquent#eager-loading
  • 然后我必须对应用层进行实际计数?我想将计数留给数据库,因为我不需要传输所有用户。我正在寻找一种方法来注入一个从数据库填充的新变量user_count
  • 查看查询生成器中addSelect() 的文档,它允许您向查询添加其他属性,并且您可以将其与join() 结合使用以包含user_count 属性

标签: php laravel eloquent


【解决方案1】:

这就是belongsToMany所需要的:

// Role model

// helper relation
public function usersCount()
{
    return $this->belongsToMany('User')
      ->selectRaw('count(users.id) as count')
      ->groupBy('pivot_role_id');
}

// accessor for $role->usersCount;
public function getUsersCountAttribute()
{
    if ( ! array_key_exists('usersCount', $this->relations)) $this->load('usersCount');

    $related = $this->getRelation('usersCount')->first();

    return ($related) ? $related->count : 0;
}

然后你可以立即加载它:

$roles = Role::with('usersCount')->get();

// pick one, for example
$roles->first()->usersCount; // int
$roles->last()->usersCount; // 0 if no related users were found

不幸的是,您当前的解决方案非常糟糕,因为它会为每个角色查询数据库。

上面的代码让您只需一次查询即可获取所有角色的计数。 另一件事是,如果没有必要,您不会加载所有相关用户,因此它不会占用您的内存(以防万一)。

【讨论】:

  • { "id": 1, "name": "Owner", "created_at": "2014-08-01 13:41:06", "users_count": [ { "user_count": 5、“id”:2、“用户名”:“emma31”、“created_at”:“2014-08-01 13:41:02”、“pivot”:{“role_id”:1、“user_id”:2} } ] }` 将从$roles->first() 返回。我认为这不是最佳的,因为它再次包含一个用户。而$roles->first()->usersCount; 让浏览器无法加载任何内容。
  • 绝对不应该挂浏览器。无论如何,它应该可以与预先加载一起使用,因此您可以轻松地将该信息附加到角色,但它在性能方面肯定不是最好的。
【解决方案2】:

尽管我感谢你们帮助我,但不幸的是,你们的解决方案都没有成功。

不过,我找到了另一个对我有帮助的 question+answer

这是我想要的完美解决方案:

Role::join('assigned_roles', 'assigned_roles.role_id', '=', 'roles.id')
        ->groupBy('roles.id')
        ->orderBy('user_count', 'desc')
        ->orderBy('name', 'asc')
        ->get(['roles.*', DB::raw('COUNT(assigned_roles.id) as user_count')]);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 2021-05-22
    • 1970-01-01
    • 2020-10-18
    • 2021-12-15
    相关资源
    最近更新 更多