2016-12-08 10 views
2

まずタイトルのことを謝り、私は何か良いものを見つけることができませんでした。ララベル関係クエリの最適化

私のプロジェクトでは、ユーザーとグループがあります。ユーザーはグループに参加してグループを作成できます。関係は以下のように定義される。私がやろうとしています何

ユーザーモデル

/** 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'); 
} 

は、ユーザーが作成したグループに参加しているすべてのユーザーを取得することです。そのために私は私のUserモデルにメソッドを書かれている:

/** 
* 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モデルにおける2つの関係:

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

おかげで、ロード時間が速くなった。この方法で、それでも重複していユーザーの問題。たとえば、私が作成した2つのグループにユーザーが参加したとします。だから私は2つのグループのためにそのユーザーを2回得るだろう。レコードをループして2回リストされたユーザーを削除できますが、それは効率的でしょうか? –

+0

更新された回答をお読みください。 –

+1

ありがとうございます。私はあなたの最初のソリューション 'merge()'と 'unique()'を使いました。 –