Laravel关系查询优化

时间:2016-12-08 12:17:13

标签: php laravel orm

首先,我为标题道歉,我找不到更好的东西。

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

用户模型

/** 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 个答案:

答案 0 :(得分: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.