2016-12-08 204 views
2

首先我为标题道歉,我找不到更好的东西。Laravel关系查询优化

在我的项目中,我有用户和组。用户可以加入一个组并创建一个组。关系定义如下。

用户模型

/** Get all the groups the user is administrator of 
* @return \Illuminate\Database\Eloquent\Relations\HasMany 
*/ 
public function groupsAdmin() 
{ 
    return $this->hasMany('App\Group','group_admin_id','id'); 
} 

组模式

/** Get the users in a group 
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo 
*/ 
public function users() 
{ 
    return $this->belongsToMany(\App\User::class,'groups_users', 'group_id','user_id'); 
} 

我所试图做的就是让所有谁参加由用户创建的组的用户。对于我在我的用户模型编写方法:

/** 
* Returns all the users who have attended groups created by this user 
*/ 
public function getPastGroupAttendees() 
{ 
    // first verify if the user is admin of any group 
    if(!$this->groupsAdmin) 
    { 
     return false; 
    } 

    $attendees = array(); 

    foreach($this->groupsAdmin as $group) 
    { 
     if(count($group->users) > 0) $attendees[] = $group->users; 
    } 
    return $attendees; 

} 

但是,使用这种方法的问题是它的慢,会得到新的数据慢。而且,由于用户可以加入多个组,因此我会从此方法获取重复的用户。 因此,如果任何人都可以向我展示一些方向来优化和纠正这个问题,那将会非常有帮助。

回答

1

您可以设置两种关系在User模型:

public function groupsAdmin() 
{ 
    return $this->hasMany('App\Group', 'group_admin_id', 'id'); 
} 

public function groups() 
{ 
    return $this->belongsToMany('App\Group'); 
} 

这是一个一对多的管理和许多一对多的组和用户(你需要在这里透视表)。

加载数据,使用eager loading

$groupWithUsers = Group::where('group_admin_id', $adminId)->with('users')->first(); 
$groupsOfUsers = User::with('groups')->get(); 

删除重复,你可以组和merge()所有用户集合遍历到一个,然后使用unique()方法来删除重复。

另一种方法是创建数据透视表的模型,并获得该组的所有用户提供简单和可读的代码:

$groups = Group::where('group_admin_id', $adminId)->pluck('id'); // Get IDs of groups. 
UserGroup::whereIn('group_id', $groups)->get()->unique(); // Get unique users from these groups. 
+0

感谢,这种方式加载时间变快,但仍然有重复用户问题。例如,用户加入了由我创建的两个组。所以我会为两个组获得该用户两次。我可以遍历记录,并删除列出两次的任何用户,但这会有效吗? –

+0

请阅读更新的答案。 –

+1

非常感谢。我用你的第一个解决方案'merge()'和'unique()'。 –