laravel eloquent 関係による並べ替え 質問する

laravel eloquent 関係による並べ替え 質問する

私は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();

おすすめ記事