【Laravel】並び替え・ソート機能を実装する|簡単な掲示板アプリの作成

Laravelで掲示板の投稿一覧に並び替え(ソート)機能を実装する方法を解説します。ドロップダウンリストでユーザーが選択した条件を受け取り、Controller側でorderByメソッドを使って投稿の表示順を動的に変更する具体的な手順が学べます。初心者でも簡単に実装できる実践的な内容です。

作成日: 更新日:

開発環境

  • OS: Windows10
  • Visual Studio Code: 1.73.0
  • PHP: 8.3.11
  • Laravel: 11.29.0
  • laravel/breeze: 2.2

サンプルコード

/app/Http/Controllers/PostController.php

/app/Http/Controllers/PostController.php
1     {
2         $query = Post::query();
3 
4+        // 絞り込み検索
5         if ($request->has('search') && $request->filled('search')) {
6             $searchType = $request->input('search_type');
7             $searchKeyword = $request->input('search');
8             }
9         }
10 
11+        // ソート処理
12+        $sortType = $request->input('sort', 'newest'); // デフォルトは「新しい順」
13+        switch ($sortType) {
14+            case 'oldest':
15+                $query->orderBy('created_at', 'asc');
16+                break;
17+            case 'title_asc':
18+                $query->orderBy('title', 'asc');
19+                break;
20+            case 'title_desc':
21+                $query->orderBy('title', 'desc');
22+                break;
23+            case 'newest':
24+                $query->orderBy('created_at', 'desc');
25+                break;
26+            default:
27+                $query->orderBy('created_at', 'desc');
28+                break;
29+        }
30+
31         $posts = $query->get();
32 
33         return view('posts.index', compact('posts'));
34

/resources/views/posts/index.blade.php

/resources/views/posts/index.blade.php
1     <a href="{{ route('posts.create') }}" class="btn btn-primary mb-3">新規投稿</a>
2 
3     <form action="{{ route('posts.index') }}" method="GET" class="mb-4">
4-        <div class="input-group">
5-            <select name="search_type" class="form-select">
6-                <option value="partial" {{ request('search_type') == 'partial' ? 'selected' : '' }}>部分一致</option>
7-                <option value="prefix" {{ request('search_type') == 'prefix' ? 'selected' : '' }}>前方一致</option>
8-                <option value="suffix" {{ request('search_type') == 'suffix' ? 'selected' : '' }}>後方一致</option>
9-            </select>
10-            <input type="text" name="search" class="form-control" placeholder="検索キーワード" value="{{ request('search') }}">
11-            <button type="submit" class="btn btn-primary">検索</button>
12+        <div class="row">
13+            <div class="col-md-8">
14+                <div class="input-group">
15+                    <select name="search_type" class="form-select">
16+                        <option value="partial" {{ request('search_type') == 'partial' ? 'selected' : '' }}>部分一致</option>
17+                        <option value="prefix" {{ request('search_type') == 'prefix' ? 'selected' : '' }}>前方一致</option>
18+                        <option value="suffix" {{ request('search_type') == 'suffix' ? 'selected' : '' }}>後方一致</option>
19+                    </select>
20+                    <input type="text" name="search" class="form-control" placeholder="検索キーワード" value="{{ request('search') }}">
21+                </div>
22+            </div>
23+
24+            <div class="col-md-2">
25+                <select name="sort" class="form-select">
26+                    <option value="newest" {{ request('sort') == 'newest' ? 'selected' : '' }}>新しい順</option>
27+                    <option value="oldest" {{ request('sort') == 'oldest' ? 'selected' : '' }}>古い順</option>
28+                    <option value="title_asc" {{ request('sort') == 'title_asc' ? 'selected' : '' }}>タイトル昇順</option>
29+                    <option value="title_desc" {{ request('sort') == 'title_desc' ? 'selected' : '' }}>タイトル降順</option>
30+                </select>
31+            </div>
32+
33+            <div class="col-md-2">
34+                <button type="submit" class="btn btn-primary">検索・ソート</button>
35+            </div>
36         </div>
37     </form>
38 
39

コード解説

変更点: ソート条件を選択するドロップダウンリストの追加

/resources/views/posts/index.blade.php
1+            <div class="col-md-2">
2+                <select name="sort" class="form-select">
3+                    <option value="newest" {{ request('sort') == 'newest' ? 'selected' : '' }}>新しい順</option>
4+                    <option value="oldest" {{ request('sort') == 'oldest' ? 'selected' : '' }}>古い順</option>
5+                    <option value="title_asc" {{ request('sort') == 'title_asc' ? 'selected' : '' }}>タイトル昇順</option>
6+                    <option value="title_desc" {{ request('sort') == 'title_desc' ? 'selected' : '' }}>タイトル降順</option>
7+                </select>
8+            </div>
9+
10+            <div class="col-md-2">
11+                <button type="submit" class="btn btn-primary">検索・ソート</button>
12+            </div>

投稿一覧画面に、並び替えの条件を選択するためのドロップダウンリストを追加しました。

<select>タグのname属性をsortに設定しています。このname属性は、フォームが送信されたときに、選択された値をどの名前でサーバー(Controller)に送るかを決める重要な役割を持ちます。

各選択肢は<option>タグで定義されています。value属性には、サーバー側で処理を判別するための値(例: newest, oldest)を設定します。ユーザーには、タグに囲まれた日本語のテキスト(例: 「新しい順」)が表示されます。

{{ request('sort') == 'newest' ? 'selected' : '' }}という部分は、並び替えを実行した後も、ユーザーが選択した条件をドロップダウンリストに表示し続けるための記述です。request('sort')で現在リクエストされているsortの値を取得し、それがその<option>valueと一致する場合にselected属性を出力します。これにより、選択された項目が最初から選ばれた状態になります。

最後に、ボタンのテキストを「検索・ソート」に変更し、このフォームが両方の機能を持つことをユーザーにわかりやすく伝えています。

変更点: ユーザーが選択した条件で投稿を並び替える処理の追加

/app/Http/Controllers/PostController.php
1+        // ソート処理
2+        $sortType = $request->input('sort', 'newest'); // デフォルトは「新しい順」
3+        switch ($sortType) {
4+            case 'oldest':
5+                $query->orderBy('created_at', 'asc');
6+                break;
7+            case 'title_asc':
8+                $query->orderBy('title', 'asc');
9+                break;
10+            case 'title_desc':
11+                $query->orderBy('title', 'desc');
12+                break;
13+            case 'newest':
14+            default:
15+                $query->orderBy('created_at', 'desc');
16+                break;
17+        }

Controller側に、ビューから送信されたソート条件に応じて、データベースから取得する投稿の順序を変更するロジックを追加しました。

まず、$request->input('sort', 'newest')の部分で、フォームから送信されたsortという名前の値を取得しています。もし値が送信されなかった場合(例えば、ユーザーが初めて一覧ページを開いた時など)は、第二引数に指定した'newest'がデフォルト値として使用されます。これにより、初期表示では自動的に「新しい順」で表示されます。

次に、switch文を使って、取得したソート条件 ($sortType) の値によって処理を分岐させています。

caseの中では、$query->orderBy()メソッドを呼び出しています。これは、データベースへの問い合わせ(クエリ)に「並び替え」の条件を追加する命令です。

  • 第一引数: 並び替えの基準となるデータベースのテーブルのカラム名(例: created_at(作成日時)やtitle(タイトル))を指定します。
  • 第二引数: 並び順を指定します。'asc'は昇順(小さい順、A→Z、古い順)、'desc'は降順(大きい順、Z→A、新しい順)を意味します。

例えば、case 'oldest':が実行されると、created_atカラムを基準に昇順(古い順)で並び替える条件がクエリに追加されます。defaultは、どのcaseにも一致しなかった場合の処理で、ここではnewest(新しい順)と同じ並び替えを行うように設定しています。

このようにして動的にorderByメソッドの条件を変えることで、ユーザーが選択した通りの順番で投稿一覧を表示する機能を実現しています。

おわりに

今回は、Laravelを使って投稿一覧に並び替え機能を実装する方法を学びました。ビュー側では<select>タグでソート条件の選択肢を用意し、フォームでコントローラーに値を送信しました。コントローラー側では、受け取った値に応じてswitch文で処理を分け、orderByメソッドの条件を動的に変更することで、柔軟な並び替えを実現しました。ユーザーの操作に応じてデータベースから取得する情報を変えるこの仕組みは、検索機能などにも応用できる非常に重要な基本となります。

関連コンテンツ