2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Laravel】カウントと並び替えでランキングを作る方法

Posted at

はじめに

今回は、LaravelのwithCountメソッドクエリビルダを使ってランキング機能を実装するまでの流れを解説していきます。

目次

  1. やりたいこと
  2. コントローラー
  3. モデル
  4. ビュー
  5. 参考

やりたいこと

タグランキングの作成
  • タグに紐付けられた記事数をカウントして多い順に並び替えます
    • 以下のテーブルを多対多(articles:tags)の関係で使用する
      • 記事テーブル(articles)
      • タグテーブル(tags)
      • 中間テーブル(article_tag)
ユーザーランキングの作成
  • ユーザーが投稿した記事のうち "status" カラムが "success" である記事をカウントして多い順に並び替えます
    • 以下のテーブルを1対多(users:articles)の関係で使用する
      • ユーザーテーブル(users)
      • 記事テーブル(articles)
DB
users articles tags article_tag
id id id id
name user_id name article_id
created_at status created_at created_at
updated_at created_at updated_at updated_at
updated_at

コントローラー

ArticleController.php
class ArticleController extends Controller
{
    public function index(Request $request)
    {
        //略

        //タグランキング
        $tags_ranking = app()->make(Tag::class)->tagsRanking();
        //達成ランキング
        $users_ranking = app()->make(User::class)->usersRanking();

        $data = [
            'tags_ranking' => $tags_ranking,
            'users_ranking' => $users_ranking,
        ];

        //略

        return view('articles.index', $data);
    }
}

モデル

リレーション結果の件数を実際にレコードを読み込むことなく知りたい場合は、withCountメソッドを使います。件数は結果のモデルの{リレーション名}_countカラムに格納されます。
(Laravel 6.x Eloquent:リレーション参照)

{リレーション名}_countカラムをテーブルに作成しなくて良いので、非常に便利です。

また、ユーザーランキングでは、Laravelのクエリビルダを活用しました。
(Laravel 6.x データベース:クエリビルダ参照)

Tag.php
class Tag extends Model
{
    public function tagsRanking()
    {
        $query = Tag::withCount('articles')->orderBy('articles_count', 'desc')->limit(5)->get();

        return $query;
    }
}
User.php

use Illuminate\Database\Eloquent\Builder;

class User extends Authenticatable
{
    public function usersRanking()
    {
        $query = User::withCount(['articles' => function (Builder $query) {
            $query->where('status', 'success');
        }])->orderBy('articles_count', 'desc')->limit(5)->get();

        return $query;
    }
}

ビューを作成

card.blade.php
{{-- タグランキング --}}
<div class="col-lg-8 col-md-10 col-sm-12 col-xs-12 mx-auto mt-5">
    <div class="card mb-4 sidebar-content">
        <div class="card-header text-center">
            <i class="fas fa-tags mr-2">
            </i>タグランキング
        </div>
        <div class="card-body main-tag-list py-3 mx-auto">
            @foreach ($tags_ranking as $tag)
                <a href="{{ route('tags.show', ['name' => $tag->name]) }}">
                    <div class="m-3">
                        {{ $tag->hashtag }}
                        <span>{{ $tag->articles_count }}</span>
                    </div>
                </a>
            @endforeach
        </div>
    </div>
</div>
{{-- タグランキング --}}

{{-- ユーザーランキング --}}
<div class="col-lg-8 col-md-10 col-sm-12 col-xs-12 mx-auto mt-5">
    <div class="card mb-4 sidebar-content">
        <div class="card-header text-center">
            <i class="fas fa-tags mr-2">
            </i>ユーザーランキング
        </div>
        <div class="card-body main-tag-list py-3 mx-auto">
            @foreach ($users_ranking as $user)
                <div class="m-3">
                    <span>{{ $user->name }}</span>
                    <span>{{ $user->articles_count }}</span>
                </div>
            @endforeach
        </div>
    </div>
</div>
{{-- ユーザーランキング --}}

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?