私は3つのモデルを持っています
- ユーザー
- チャネル
- 返事
モデル関係
user
持っているbelongsToMany('App\Channel');
channel
持っているhasMany('App\Reply', 'channel_id', 'id')->oldest();
チャンネルが2つあるとしましょう
- チャンネル1
- チャンネル2
channel-2
最新の返信はchannel-1
今、私はユーザーのチャンネルをそのチャンネルの現在の返信順に並べたいと思っています。ちょうどチャット アプリケーションのように。ユーザーのチャンネルをこのように並べるにはどうすればよいでしょうか?
- チャンネル2
- チャンネル1
すでにいくつかのコードを試しました。しかし何も起こりませんでした
// User Model
public function channels()
{
return $this->belongsToMany('App\Channel', 'channel_user')
->withPivot('is_approved')
->with(['replies'])
->orderBy('replies.created_at'); // error
}
// also
public function channels()
{
return $this->belongsToMany('App\Channel', 'channel_user')
->withPivot('is_approved')
->with(['replies' => function($qry) {
$qry->latest();
}]);
}
// but i did not get the expected result
編集また、これを試してみました。確かに期待通りの結果が得られましたが、応答がない場合はすべてのチャネルが読み込まれませんでした。
public function channels()
{
return $this->belongsToMany('App\Channel')
->withPivot('is_approved')
->join('replies', 'replies.channel_id', '=', 'channels.id')
->groupBy('replies.channel_id')
->orderBy('replies.created_at', 'ASC');
}
ベストアンサー1
私の知る限りでは、熱心な負荷 with
メソッドは2番目のクエリを実行します。そのため、熱心な読み込み with
方法。
join
私は、この方法を組み合わせて使うと思います関係メソッド解決策は、次のとおりです。以下の解決策は完全にテストされており、正常に動作します。
// In User Model
public function channels()
{
return $this->belongsToMany('App\Channel', 'channel_user')
->withPivot('is_approved');
}
public function sortedChannels($orderBy)
{
return $this->channels()
->join('replies', 'replies.channel_id', '=', 'channel.id')
->orderBy('replies.created_at', $orderBy)
->get();
}
その後、電話して$user->sortedChannels('desc')
リストを入手することができますチャンネル返信created_at
属性で並べ替えます。
次のような条件の場合チャンネル(返信がある場合とない場合があります)、leftJoin
メソッドを使用するだけです。
public function sortedChannels($orderBy)
{
return $this->channels()
->leftJoin('replies', 'channel.id', '=', 'replies.channel_id')
->orderBy('replies.created_at', $orderBy)
->get();
}
編集:
groupBy
クエリにメソッドを追加したい場合は、orderBy
句に特別な注意を払う必要があります。SQL性質上、Group By
節はOrder By
節の前に最初に実行されます。この問題の詳細については、このスタックオーバーフローの質問。
したがって、groupBy
メソッドを追加する場合は、メソッドを使用する必要がありorderByRaw
、次のように実装する必要があります。
return $this->channels()
->leftJoin('replies', 'channels.id', '=', 'replies.channel_id')
->groupBy(['channels.id'])
->orderByRaw('max(replies.created_at) desc')
->get();