##はじめに
メディア系サイトを構築している際、ユーザーや投稿をランキング形式で取得したい場合があるかと思います。
ランキングの基準を「いいね」数にしている場合投稿
といいね
を別テーブルにし、リレーションを設定するのが一般的だと思います。
リレーション先のいいね数をカウントしてソートします。
##何が問題か?
Laravel Eloquent
を用いてソートを実装する場合orderBy
を使用します。
ProductController.php
public function list()
{
$products = Product::with('likes')->orderBy(Product::CREATED_AT, 'desc')->paginate();
return $products;
}
orderBy
はテーブルのカラムを利用して(第一引数)降順・昇順(第二引数)を決定します。
そのためcount()を用いて「いいね」数を取得してもそれはカラムではないため、orderByできません。
##実装
withcount()
を使用します。引数に取得したいリレーションテーブル名を入れると'○○_count'というデータをカラム扱いとして取得できます。この値はカラム扱いなため、きちんとorderBy
できます。
ProductController.php
public function list()
{
$products = Product::withCount('likes')->orderBy('likes_count', 'desc')->paginate();
return $products;
}