モデルの作成者がFooモデルの結果をフィルタリングするクエリスコープメソッドがあります。複雑なのは、作者が直接関係していないことです。
FooはBarに属し、BarはUserに属しています。 Fooがユーザーに属している場合は、次のようにすることができます。
public function scopeAuthorOnly($query, User $user)
{
return $query->whereuser_id($user->id);
}
Fooモデルにはuser_id列がなく、代わりにbar_id列があるため、これは明らかに機能しません。ただし、user_idをフィルタリングする方法でクエリを作成する方法がわかりません。
ポインタはありますか?
解決策を見つけました:
public function scopeAuthorOnly($query, User $user)
{
$query
->join('bars', 'foos.bar_id', '=', 'bars.id')
->join('users', 'bars.user_id', '=', 'users.id')
->where('users.id', '=', $user->id);
return $query;
}
スコープでwhereHas()
を使用して、関係を照会できます。
このモデルにusers()
関係関数があると仮定しましょう。次に、次のようになります。
public function scopeAuthorOnly($query, User $user)
{
return $query->whereHas('users', function($q) use($user){
$q->where('id', $user->id);
});
}
更新:whereHas
ステートメントをネストすることもできます:現在のFoo
にbar
という名前の関係があり、bar
にusers
という名前の関係がある場合、次のようになります。この:
public function scopeAuthorOnly($query, User $user)
{
return $query->whereHas('bar', function($q) use($user){
return $q->whereHas('users', function($q2) use($user){
$q2->where('id', $user->id);
});
});
}
詳細: ここ
リレーションを使用してこれを行うこともできます(手動結合に頼ることなく):
public function scopeAuthorOnly($query, User $user)
{
$query->whereHas(array('Bar' => function($query) use($user){
$query->where('user_id', '=', $user->id);
}));
}
編集:whereHas
の代わりにwith
を使用するようになりました(Laravel> = 4.1のみ)。訂正アルダをありがとう。
編集:4.2では、whereHasの構文が変更されたため、リレーションシップ名はパラメーター1であり、クロージャーはパラメーター2です(配列として渡されるのではありません)。
public function scopeAuthorOnly($query, User $user)
{
$query->whereHas('Bar', function($query) use($user){
$query->where('user_id', '=', $user->id);
});
}