2016-12-08 5 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'); 
} 

Group Модель

/** 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()'. –

Смежные вопросы