Laravelのページングは、取得条件と並び順を決めたQuery Builder/Eloquentへpaginateを指定し、結果をBladeへ渡して表示します。元の手順にある引用符の欠落を訂正し、同じ日時の行やJOIN、SQL本数、リンクの引継ぎも分けて確認します。
訂正版:取得条件と一意な並び順
以下はLaravel 13で確認した学習用クラスです。usersにはid/name/created_at/delete_flag、結合例には記載した独自列がある前提で、既存アプリへテーブルを作る指示ではありません。モデルのスコープを使わないQuery Builderの例なので、実装時は必要な権限・公開条件を自分で追加します。
<?php
namespace ContentExamples;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\Query\Builder;
final class PageQueries
{
public static function users(ConnectionInterface $db): Builder
{
return $db->table('users')
->select('id', 'name', 'created_at')
->where('delete_flag', 0)
->orderByDesc('created_at')
->orderByDesc('id');
}
public static function tweets(ConnectionInterface $db, string $since): Builder
{
return $db->table('ret_t_tweet')
->join('ret_m_user', 'ret_t_tweet.user_id', '=', 'ret_m_user.id')
->where('ret_m_user.delete_flag', 0)
->where('ret_t_tweet.created_at_shaped', '>=', $since)
->select(
'ret_t_tweet.id as tweet_id',
'ret_t_tweet.tweet_url',
'ret_t_tweet.text',
'ret_t_tweet.created_at_shaped',
'ret_m_user.id as user_id',
'ret_m_user.name as user_name'
)
->orderByDesc('ret_t_tweet.created_at_shaped')
->orderByDesc('ret_t_tweet.id');
}
}
クラスをautoloadできる位置へ配置するか読み込み、コントローラー内では次のようにページャーを作ります。名前空間・接続名・ビュー名は自分の構成へ合わせます。ここで件数は固定し、入力値で無制限に大きくしません。
$users = \ContentExamples\PageQueries::users(\Illuminate\Support\Facades\DB::connection())
->paginate(10);
return view('users.index', ['users' => $users]);Bladeで一覧とリンクを表示する
次はresources/views/users/index.blade.phpに相当するビュー例です。ユーザー名は通常の二重波括弧でエスケープし、空結果も表示します。linksのCSSは使用するTailwind/Bootstrap等のページャービューに合わせます。
<ul>
@forelse ($users as $user)
<li>{{ $user->name }}</li>
@empty
<li>該当するユーザーはいません。</li>
@endforelse
</ul>
{{ $users->links() }}
方式・検索条件・ページ境界の選び方
| 方式 | 使い分け |
|---|---|
| paginate | 総件数・ページ番号が必要な一覧。通常は件数取得と一覧取得を行うが、空結果・指定total・関連取得等で本数は変わる |
| simplePaginate | 総件数を出さない前後移動。次の行の有無を調べるため指定件数より1行多く取得する |
| cursorPaginate | 一意なキーの位置から続きを取得。ページ番号での任意移動とは異なり、NULL不可等の条件を公式資料で確認する |
日時とidの順序を固定しても、ページ移動中の追加・削除によるOFFSETの位置ずれは防げません。 検証では先頭への追加後に2ページ目の行がずれることも確認しました。カーソル方式も、順序列の更新や削除を含む完全なスナップショットの保証ではありません。
- 検索条件を変えたらpageを1へ戻す。リンクへ残すのは検証し、実際にWHEREへ適用した許可キーだけにする。
- withQueryStringは全クエリを引継ぐため、トークンや個人情報を含むURLでは安易に使わない。appendsも渡したキーを検証してくれる機能ではない。
- 同じ画面に複数のページャーがあるなら、paginateの第3引数でusers_page等の別名を指定する。ページ指定の読み取りとフォームのhidden値も合わせる。
- 遅い場合は総件数・一覧・関連取得を分けて測る。get後のCollectionをそのままDBクエリと同じものとして扱わず、深いOFFSETをsimplePaginateだけで解消できるとは考えない。
公式: Laravel Pagination。SQL条件はQuery Builder、実際の本数はSQLログの確認方法へ進めます。以下は元のコード表を保持した記録で、上の訂正と区別してください。
| この記事の要点 |
|---|
|
サーバー側の処理
次の黒い表は旧コードです。 orderByのcreated_atの閉じ引用符が欠けており、そのままではPHPの構文エラーになります。訂正はorderBy('created_at', 'DESC')です。同じ日時の行に備え、一意なidも並び順へ追加してください。Usersというモデル名もアプリに実在するものへ合わせます。
|
$users = Users::where('delete_flag', 0) |
取得条件・一意な順序を定義してからpaginateを呼びます。ページ番号が範囲外なら空結果になる場合があり、自動的に404へ変わるとは限りません。
引数には1ページに表示する件数を定義。
取得結果をBladeテンプレート側に渡す。
クライアント側の処理
|
{{ $users->links() }} |
Bladeテンプレート側は上記の定義だけでページング用のリンクが自動生成される。(page=n のパラメータが自動で付与される)
以下の旧appends例は$idが定義され、検索条件として適用済みの場合の断片です。appendsはリンクへ値を加えるだけで、SQLのWHEREや入力検証・閲覧権限を追加しません。秘密値や不要なクエリをリンクへ転送しないでください。
|
{{ $users->appends(['id' => $id])->links() }} |
サーバー側のもう少し複雑なSQLの実行例
次はmysql2接続、独自テーブルと$todayを使う旧断片です。接続設定・時刻の基準・列の型が必要で、このまま動く汎用例ではありません。ORDER BYがないのでページの並びは安定しません。上の訂正版ではtweet側の日時と主キーを指定し、user_idとtweet_idを分けています。JOINが1対多なら件数は親の数ではなく結合後の行数になる点も確認してください。
|
$results = DB::connection('mysql2') |
子ページはありません
- インストールと設定
- クイックスタート & チュートリアル(初心者向け)
- クイックスタート & チュートリアル(中級者向け)
- ルーティング
- Bladeテンプレート(ビュー/レイアウト)
- コントローラー
- マイグレーションとテーブル定義
- データベースの設定
- Eloquentモデル (ORM)
- SQLとクエリビルダー
- バリデーション
- .envファイルの設定値へのアクセス
- 動作環境による分岐処理
- configフォルダ配下の設定値へのアクセス
- assetヘルパーを利用したpublicフォルダへのアクセス
- storageフォルダへのアクセス
- アプリケーション名の変更
- メンテナンス
- ログイン画面(認証システム)の作成
- ログインの必須化
- ログインユーザー情報の取得
- ルートの認証化
- 本番サーバーへのデプロイ方法
- 多言語化
- csrf_field
- ファイルのダウンロード
- CSVのアップロードおよび読み込み(maatwebsite/excel)
- ページタイトルの設定
- コマンド一覧
- エラー一覧
- SQLの実行ログ出力方法
- キャッシュのクリア
- Selectの結果の最初もしくは最後に任意の値を追加する方法
- ajaxでPOST通信する際の注意点
- ソーシャルログインの実装
- セッション情報の確認
- ログイン、ユーザー登録、パスワードリセット後のリダイレクト先の変更方法
- redirectやreturn viewにメッセージを付与する方法
- クッキー(cookie)の設定と取得
- クラスの再読み込み
- csrfの有効時間を変更する方法
- ViewComposerを用いてviewに共通の値を付与する方法
- View::shareを用いて共通の値を各ビューに渡す方法
- ミドルウェアを用いた処理の共通化
- Middleware内でAuth::check()などを使用する方法
- Controller以外でリダイレクトする方法
- セッションの値の取得/保存/更新/削除
- $requestの値を変更する方法
- 常時SSL化
- ページング(ページネーション)をする方法
- vue.jsとの連携
- Vue.jsと連携するSPA実行環境構築
- .envの値をvue.jsで参照する方法
- vue.jsを本番環境にリリースする方法
- could not find driver(Windows, MySQL編)
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスのソフト一覧|Blender・Metasequoiaと用途別の選び方
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Visual Studio「デザイナーを表示できません」エラーの原因と対処 2026-10-28 12:06:00
- SSH 認証に失敗しました。再試行してください の対処 2026-10-28 12:06:00
- SSH2 秘密鍵の読み込みに失敗しました の原因と対処 2026-10-28 12:06:00
- TeraTerm のよくあるエラーと対処法完全ガイド — Connection refused / 2026-10-28 12:06:00
- Visual Studio エラー一覧|コンパイルエラー・警告の確認方法と対処 2026-10-28 11:39:57
- Whitelabel Error Page の原因と消し方|Spring Boot のエラーページ 2026-10-28 11:39:57
- Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法 2026-10-28 11:39:57
- SQL WHERE 句完全ガイド 2026-10-28 11:39:57
- SQL JOIN 完全ガイド (INNER/LEFT/RIGHT/FULL OUTER) 2026-10-28 11:39:57
- tomcat の起動 / 停止ログと catalina.log・catalina.out の違い 2026-10-28 10:24:23
- Tomcat の起動確認方法 5 つ|localhost:8080・ポート・プロセス・ログ 2026-10-28 10:24:23
- Oracle 19c COMMITの使い方: 暗黙コミット・自動確定・応答不明時の確認 2026-10-28 09:59:09
- Oracle 19c DELETE文|削除対象の確認・COMMIT前の判断・ROLLBACKの条件 2026-10-28 09:59:09
- Oracle 19c INSERT文|INSERT ALL・SELECT・RETURNINGとMERGEの使い分け 2026-10-28 09:59:09
- Oracle 19cのトランザクション制御|COMMIT・ROLLBACK・分離レベルと接続設定 2026-10-28 09:59:09