2016-12-08 156 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()'。 –