【Laravel】ページネーション機能を実装する|簡単な掲示板アプリの作成
Laravelのページネーション機能を使って、掲示板の投稿一覧やコメントを複数ページに分割して表示する方法を学びます。`paginate()`メソッドでのデータ取得から、Bootstrapでデザインを整えたページリンクの表示方法までを、初心者にもわかりやすく解説します。
開発環境
- 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.php1 break; 2 } 3 4- $posts = $query->get(); 5+ $posts = $query->paginate(5); 6 7 return view('posts.index', compact('posts')); 8 } 9 public function show(string $id) 10 { 11 $post = Post::with('comments.user')->findOrFail($id); 12- return view('posts.show', compact('post')); 13+ $comments = $post->comments()->with('user')->paginate(5); 14+ return view('posts.show', compact('post', 'comments')); 15 } 16 17 /** 18
/app/Providers/AppServiceProvider.php
/app/Providers/AppServiceProvider.php1 namespace App\Providers; 2 3 use Illuminate\Support\ServiceProvider; 4+use Illuminate\Pagination\Paginator; 5 6 class AppServiceProvider extends ServiceProvider 7 { 8 */ 9 public function boot(): void 10 { 11- // 12+ Paginator::useBootstrapFive(); 13 } 14 } 15
/resources/views/posts/index.blade.php
/resources/views/posts/index.blade.php1 </div> 2 </form> 3 4+ <!-- 投稿のリスト表示 --> 5 @foreach ($posts as $post) 6 <div class="card mb-3"> 7 <div class="card-body"> 8 </div> 9 </div> 10 @endforeach 11+ 12+ <!-- ページネーションリンク --> 13+ <div class="d-flex justify-content-center mt-4"> 14+ {{ $posts->links() }} 15+ </div> 16 @endsection 17
/resources/views/posts/show.blade.php
/resources/views/posts/show.blade.php1 2 {{-- コメント一覧 --}} 3 <h3>コメント一覧</h3> 4- @if ($post->comments->isEmpty()) 5+ @if ($comments->isEmpty()) 6 <p>コメントはまだありません。</p> 7 @else 8- @foreach ($post->comments as $comment) 9+ @foreach ($comments as $comment) 10 <div class="card mb-2"> 11 <div class="card-body"> 12 <p class="card-text">{{ $comment->content }}</p> 13 @else 14 <p>コメントを投稿するにはログインしてください。</p> 15 @endauth 16+ 17+ {{-- コメントのページネーションリンク --}} 18+ <div class="d-flex justify-content-center mt-4"> 19+ {{ $comments->links() }} 20+ </div> 21+ 22 @endsection 23
コード解説
変更点: 投稿一覧をページネーションで取得
/app/Http/Controllers/PostController.php1- $posts = $query->get(); 2+ $posts = $query->paginate(5); 3 4 return view('posts.index', compact('posts')); 5 }
これまでデータベースから全ての投稿を取得するために使っていた get() メソッドを paginate(5) メソッドに変更しました。get() は条件に合う全てのデータを一度に取得しますが、paginate() は指定した数(この場合は5件)ごとにデータを区切って取得します。これにより、大量の投稿があってもページごとに分割して表示できるようになります。
変更点: コメント一覧をページネーションで取得
/app/Http/Controllers/PostController.php1 public function show(string $id) 2 { 3 $post = Post::with('comments.user')->findOrFail($id); 4- return view('posts.show', compact('post')); 5+ $comments = $post->comments()->with('user')->paginate(5); 6+ return view('posts.show', compact('post', 'comments')); 7 }
投稿詳細ページで表示するコメントの取得方法を変更しました。以前は $post->comments ですべてのコメントを取得していましたが、これだとコメントが増えた際にページの表示が遅くなる可能性があります。そこで、特定の投稿に紐づくコメントを $post->comments() という形でクエリとして取得し、それに対して paginate(5) を適用しています。これにより、コメントも1ページあたり5件ずつ表示されるようになります。取得したコメントデータは新しく $comments という変数に入れ、compact() を使ってビューに渡しています。
変更点: Paginatorクラスのインポート
/app/Providers/AppServiceProvider.php1 namespace App\Providers; 2 3 use Illuminate\Support\ServiceProvider; 4+use Illuminate\Pagination\Paginator; 5 6 class AppServiceProvider extends ServiceProvider 7 {
この変更では、Laravelのページネーション機能をカスタマイズするために必要な Paginator クラスを use を使って読み込んでいます。ファイル内で外部のクラスを使用する際には、このようにファイルの先頭で「このクラスを使います」と宣言する必要があります。
変更点: ページネーションのデザインをBootstrap 5に設定
/app/Providers/AppServiceProvider.php1 */ 2 public function boot(): void 3 { 4- // 5+ Paginator::useBootstrapFive(); 6 } 7 }
Laravelが生成するページネーションリンクのHTMLデザインを、CSSフレームワークであるBootstrap 5に対応させるための設定です。AppServiceProvider.php の boot メソッドに Paginator::useBootstrapFive(); と記述することで、アプリケーション全体でページネーションのデザインが自動的にBootstrap 5のスタイルになります。boot メソッドはアプリケーションの起動時に実行されるため、ここに記述することで全体に設定が適用されます。
変更点: 投稿一覧にページネーションリンクを表示
/resources/views/posts/index.blade.php1 @foreach ($posts as $post) 2 <div class="card mb-3"> 3 <div class="card-body"> 4 </div> 5 </div> 6 @endforeach 7+ 8+ <!-- ページネーションリンク --> 9+ <div class="d-flex justify-content-center mt-4"> 10+ {{ $posts->links() }} 11+ </div> 12 @endsection
コントローラーから渡された $posts 変数を使って、ページネーションリンク(「1, 2, 3...」や「次へ」といったリンク)をビューに表示します。paginate() メソッドで取得したデータは、links() メソッドを持っています。このメソッドを {{ }} で呼び出すだけで、Laravelが自動的に現在のページや総ページ数を計算し、適切なHTMLリンクを生成してくれます。d-flex justify-content-center はBootstrapのクラスで、リンクを中央に配置するためのものです。
変更点: ビューで受け取るコメント変数の変更
/resources/views/posts/show.blade.php1 {{-- コメント一覧 --}} 2 <h3>コメント一覧</h3> 3- @if ($post->comments->isEmpty()) 4+ @if ($comments->isEmpty()) 5 <p>コメントはまだありません。</p> 6 @else 7- @foreach ($post->comments as $comment) 8+ @foreach ($comments as $comment) 9 <div class="card mb-2"> 10 <div class="card-body"> 11 <p class="card-text">{{ $comment->content }}</p>
コントローラーの show メソッドで、ページネーション化されたコメントを新しく $comments という変数でビューに渡すように変更しました。そのため、ビュー側もその変更に合わせる必要があります。これまでコメントの有無の判定や一覧表示に使っていた $post->comments を、新しく渡された $comments 変数に書き換えています。
変更点: コメント一覧にページネーションリンクを表示
/resources/views/posts/show.blade.php1 @else 2 <p>コメントを投稿するにはログインしてください。</p> 3 @endauth 4+ 5+ {{-- コメントのページネーションリンク --}} 6+ <div class="d-flex justify-content-center mt-4"> 7+ {{ $comments->links() }} 8+ </div> 9+ 10 @endsection
投稿一覧ページと同様に、コメント一覧の下にもページネーションリンクを追加します。コントローラーから渡された $comments 変数に対して links() メソッドを呼び出すことで、コメント用のページネーションリンクがHTMLとして生成・表示されます。これにより、ユーザーはコメントをページ単位で閲覧できるようになります。
おわりに
おわりに
今回はLaravelのページネーション機能について学びました。コントローラーでデータの取得方法をget()からpaginate()メソッドに変更するだけで、簡単にページ分割が実現できます。ビュー側ではlinks()メソッドを呼び出すだけでページリンクが自動で生成され、AppServiceProviderに一行追加するだけでBootstrapのデザインを適用できる手軽さもご理解いただけたと思います。