はじめに
題名の通りですが、ある商品の購入者数をカウントしたい場合があるとします。
同じ人が何回購入しても、売れた個数を1個としてカウントしたい場合の処理を紹介します。
ランキングを表示する際に同じ人が何度も購入してた場合、その購入数を1回でカウントしたい時に実装しました。
目次
テーブル構成
まずはテーブル構成ですが、goods、payments、usersテーブルがあるとします。
リレーションの処理はこちらでは省略しますので、自身で書いて下さい。
【テーブル構成】
users → ユーザー情報
goods → 商品の情報
payments → 購入履歴情報 (中間テーブル)
※paymentsは中間テーブルなので、goods_idとuser_idを持っています。
商品のランキング表示処理
・withCountで、ある商品のグッズの購入数を取得できます。
・同じユーザーが複数回購入しても1回でカウントする為にdistinctを用いています。
distinct → 重複するuser_idを1つにまとめる。
・最後にorderByで購入者が多い順に並べ替えています。
// GoodsController.php
// 商品ランキングページを表示する処理
public function index()
{
// グッズの購入人数を取得して、人数順に並び替える
$goods_ranking = Goods::getPaymentsCount()->orderBy('payments_count', 'DESC');
return view('user.index', ['goods_ranking' => $goods_ranking]);
}
// app/Models/Goods.php
public function scopeGetPaymentsCount($query)
{
// withCountでリレーション先のそのグッズの購入数を取得する
return $query->withCount(['payments' => function ($query) {
// distinctで重複する。user_idを1つにまとめる
$query->select(DB::raw('count(distinct(`user_id`))'));
}]);
}
試してダメだった事
クエリビルダーのgroupByとwithCountを組み合わせて取得してみましたが、エラーが出て、うまく取得できませんでした。
いけそうでいけないです・・・良い方法があれば教えて頂きたいです!!
public function scopeGetPaymentsCount($query)
{
// withCountでリレーション先のそのグッズの購入数を取得する
return $query->withCount(['payments' => function ($query) {
// groupByで重複する。user_idを1つにまとめる・・・事が出来ませんでした・・・
$query->groupBy('user_id');
}]);
}
最後に
ちなみにクエリビルダーのjoinとgroupByを組み合わせても実装自体は可能です。
経験が浅いので、良い方法があれば是非教えて下さい!!
ここまで読んで頂き、ありがとうございました。