我在使用Laravel 4和Elqouent时遇到了问题。我的模型实现了以下关系:
用户 belongsToMany 角色
角色 belongsToMany 用户
我想查询角色,并希望获得相关用户的计数。
当我执行以下操作时,我遇到了N + 1问题:
$role = Role::has('users')->get()->each(function($role) {
$role->user_count = $role->users()->count();
});
有什么我没想过的吗?
答案 0 :(得分: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
不幸的是,您当前的解决方案非常糟糕,因为它会查询每个角色的数据库。
上面的代码允许您只使用一个查询来获取所有角色的计数。 另一件事是,如果没有必要,你不会加载所有相关用户,所以它不会占用你的记忆(如果它很重要)。
答案 1 :(得分:1)
尽管我很感谢你们帮助我,但不幸的是,你的解决方案都没有真正做到这一点。
我找到了另一个帮助我的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')]);