Php 雄辩的关系计数

Php 雄辩的关系计数,php,laravel,eloquent,Php,Laravel,Eloquent,我对Laravel 4和Elqount有问题。我的模型实现了以下关系: 用户属于任何角色 角色归属于任何用户 我想查询角色,并想获得与它们相关的用户数 当我执行以下操作时,我遇到了N+1问题: $role = Role::has('users')->get()->each(function($role) { $role->user_count = $role->users()->count(); }); 有什么我没想到的吗?这就是你需要的 // Role

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

用户属于任何角色
角色归属于任何用户

我想查询角色,并想获得与它们相关的用户数

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

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

有什么我没想到的吗?

这就是你需要的

// 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

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

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

尽管我非常感谢您的帮助,但不幸的是,您的两个解决方案都没有真正起到作用

不过,我找到了另一个对我有帮助的人

这是一个完全符合我要求的解决方案:

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')]);

与()合并并具有()。仅供参考,如果您只使用with(),您将得到包含没有角色的用户的结果。然后我必须在应用层上进行实际计数?我想留下数据库的计数,因为我不需要传输所有的用户。我正在寻找一种方法来注入从数据库中填充的新变量
user\u count
。查看查询生成器中
addSelect()
的文档,它允许您向查询中添加其他属性,您可以将其与
join()
组合,以包含
user\u count
属性{“id”:1,“name”:“Owner”,“created_at”:“2014-08-01 13:41:06”,“users_count”:[{“user_count”:5,“id”:2,“username”:“emma31”,“created_at”:“2014-08-01 13:41:02”,“pivot”:{“role_id”:1,“user_id”:2}}]}`将从
$roles->first()
返回。我认为这不是最优的,因为它再次包含一个用户。并且
$roles->first())->UserScont;
使浏览器无法加载任何内容。它不应该明确地挂起浏览器。无论如何,它应该能够与快速加载一起工作,因此您可以轻松地将该信息附加到角色,尽管它在性能方面不是最好的。