はじめに

他のフレームワークでは、ページネーションは非常に面倒です。Laravelのページネーションのアプローチが新鮮な風になることを期待しています。Laravelのページネーターは、クエリビルダーEloquent ORMに統合されており、ゼロ設定でデータベースレコードの便利で使いやすいページネーションを提供します。

デフォルトでは、ページネーターによって生成されるHTMLはTailwind CSSフレームワークと互換性がありますが、Bootstrapのページネーションサポートも利用可能です。

Tailwind JIT

LaravelのデフォルトのTailwindページネーションビューとTailwind JITエンジンを使用している場合は、アプリケーションのtailwind.config.jsファイルのcontentキーがLaravelのページネーションビューを参照していることを確認し、Tailwindクラスが削除されないようにしてください:

  1. content: [
  2. './resources/**/*.blade.php',
  3. './resources/**/*.js',
  4. './resources/**/*.vue',
  5. './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
  6. ],

基本的な使用法

クエリビルダー結果のページネーション

アイテムをページネートする方法はいくつかあります。最も簡単なのは、クエリビルダーまたはEloquentクエリpaginateメソッドを使用することです。paginateメソッドは、ユーザーが表示している現在のページに基づいてクエリの「制限」と「オフセット」を自動的に設定します。デフォルトでは、現在のページはHTTPリクエストのpageクエリ文字列引数の値によって検出されます。この値はLaravelによって自動的に検出され、ページネーターによって生成されたリンクにも自動的に挿入されます。

この例では、paginateメソッドに渡される唯一の引数は、「ページごとに表示したいアイテムの数」です。この場合、15アイテムをページごとに表示したいと指定しましょう:

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Controllers\Controller;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\View\View;
  6. class UserController extends Controller
  7. {
  8. /**
  9. * Show all application users.
  10. */
  11. public function index(): View
  12. {
  13. return view('user.index', [
  14. 'users' => DB::table('users')->paginate(15)
  15. ]);
  16. }
  17. }

シンプルなページネーション

  1. したがって、アプリケーションのUIにシンプルな「次へ」と「前へ」リンクのみを表示する必要がある場合は、`````simplePaginate`````メソッドを使用して単一の効率的なクエリを実行できます:
  2. ``````php
  3. $users = DB::table('users')->simplePaginate(15);
  4. `

Eloquent結果のページネーション

Eloquent[$3a3cc29cc73636fb.md]クエリもページネートできます。この例では、App\Models\Userモデルをページネートし、ページごとに15レコードを表示する予定であることを示します。ご覧のとおり、構文はクエリビルダー結果のページネーションとほぼ同じです:

  1. use App\Models\User;
  2. $users = User::paginate(15);

もちろん、paginateメソッドを呼び出す前に、where句などの他の制約をクエリに設定することができます:

  1. $users = User::where('votes', '>', 100)->paginate(15);

Eloquentモデルをページネートする際にsimplePaginateメソッドを使用することもできます:

  1. $users = User::where('votes', '>', 100)->simplePaginate(15);

同様に、cursorPaginateメソッドを使用してEloquentモデルをカーソルページネートすることもできます:

  1. $users = User::where('votes', '>', 100)->cursorPaginate(15);

ページごとの複数のページネーターインスタンス

時には、アプリケーションによってレンダリングされる単一の画面に2つの別々のページネーターをレンダリングする必要がある場合があります。ただし、両方のページネーターインスタンスが現在のページを保存するためにpageクエリ文字列パラメータを使用している場合、2つのページネーターが競合します。この競合を解決するには、paginatesimplePaginatecursorPaginateメソッドに提供される3番目の引数を介して、ページネーターの現在のページを保存するために使用したいクエリ文字列パラメータの名前を渡すことができます:

  1. use App\Models\User;
  2. $users = User::where('votes', '>', 100)->paginate(
  3. $perPage = 15, $columns = ['*'], $pageName = 'users'
  4. );

カーソルページネーション

  1. オフセットベースのページネーションとは異なり、ページネーターによって生成されたURLのクエリ文字列にページ番号を含めるのではなく、カーソルベースのページネーションはクエリ文字列に「カーソル」文字列を配置します。カーソルは、次のページネートクエリがどこから開始すべきか、どの方向にページネートすべきかを示すエンコードされた文字列です:
  2. ``````nothing
  3. http://localhost/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0
  4. `

クエリビルダーが提供するcursorPaginateメソッドを介してカーソルベースのページネーターインスタンスを作成できます。このメソッドはIlluminate\Pagination\CursorPaginatorのインスタンスを返します:

  1. $users = DB::table('users')->orderBy('id')->cursorPaginate(15);

カーソルページネーターインスタンスを取得したら、通常のpaginateおよびsimplePaginateメソッドを使用してページネーション結果を表示できます。カーソルページネーターが提供するインスタンスメソッドの詳細については、カーソルページネーターインスタンスメソッドのドキュメントを参照してください。

クエリには、カーソルページネーションを利用するために「order by」句が含まれている必要があります。また、クエリが順序付けられている列は、ページネートしているテーブルに属している必要があります。

カーソルとオフセットページネーション

オフセットページネーションとカーソルページネーションの違いを示すために、いくつかのSQLクエリの例を見てみましょう。以下の2つのクエリは、usersテーブルの「2ページ目」の結果を表示します。idで順序付けられています:

  1. # オフセットページネーション...
  2. select * from users order by id asc limit 15 offset 15;
  3. # カーソルページネーション...
  4. select * from users where id
  5. > 15 order by id asc limit 15;

カーソルページネーションクエリは、オフセットページネーションに対して以下の利点を提供します:

  • 大規模なデータセットの場合、「order by」列がインデックスされていると、カーソルページネーションはより良いパフォーマンスを提供します。これは、「オフセット」句がすべての以前に一致したデータをスキャンするためです。
  • 書き込みが頻繁なデータセットの場合、オフセットページネーションは、ユーザーが現在表示しているページに最近追加または削除された結果があると、レコードをスキップしたり重複を表示したりする可能性があります。

ただし、カーソルページネーションには以下の制限があります:

  • simplePaginateのように、カーソルページネーションは「次へ」と「前へ」リンクを表示するためにのみ使用でき、ページ番号を持つリンクの生成をサポートしていません。
  • 少なくとも1つのユニークな列またはユニークな列の組み合わせに基づいて順序付けされる必要があります。null値を持つ列はサポートされていません。
  • 「order by」句のクエリ式は、エイリアスが付けられ、選択句にも追加されている場合にのみサポートされます。
  • パラメータを持つクエリ式はサポートされていません。

ページネーターの手動作成

時には、メモリ内にすでにあるアイテムの配列を渡してページネーションインスタンスを手動で作成したい場合があります。その場合、Illuminate\Pagination\PaginatorIlluminate\Pagination\LengthAwarePaginator、またはIlluminate\Pagination\CursorPaginatorインスタンスを作成できます。

  1. 言い換えれば、`````Paginator`````はクエリビルダーの`````simplePaginate`````メソッドに対応し、`````CursorPaginator``````````cursorPaginate`````メソッドに対応し、`````LengthAwarePaginator``````````paginate`````メソッドに対応します。
  2. ページネーターインスタンスを手動で作成する際は、ページネーターに渡す結果の配列を手動で「スライス」する必要があります。これを行う方法がわからない場合は、[array_slice](https://secure.php.net/manual/en/function.array-slice.php) PHP関数を確認してください。
  3. <a name="customizing-pagination-urls"></a>
  4. ### ページネーションURLのカスタマイズ
  5. デフォルトでは、ページネーターによって生成されるリンクは、現在のリクエストのURIに一致します。ただし、ページネーターの`````withPath`````メソッドを使用すると、リンクを生成する際にページネーターが使用するURIをカスタマイズできます。たとえば、ページネーターに`````http://example.com/admin/users?page=N`````のようなリンクを生成させたい場合は、`````/admin/users``````````withPath`````メソッドに渡す必要があります:
  6. ``````php
  7. use App\Models\User;
  8. Route::get('/users', function () {
  9. $users = User::paginate(15);
  10. $users->withPath('/admin/users');
  11. // ...
  12. });
  13. `

クエリ文字列値の追加

ページネーションリンクのクエリ文字列に追加するには、appendsメソッドを使用できます。たとえば、各ページネーションリンクにsort=votesを追加するには、appendsに次の呼び出しを行う必要があります:

  1. use App\Models\User;
  2. Route::get('/users', function () {
  3. $users = User::paginate(15);
  4. $users->appends(['sort' => 'votes']);
  5. // ...
  6. });

現在のリクエストのすべてのクエリ文字列値をページネーションリンクに追加したい場合は、withQueryStringメソッドを使用できます:

  1. $users = User::paginate(15)->withQueryString();

ハッシュフラグメントの追加

ページネーターによって生成されたURLに「ハッシュフラグメント」を追加する必要がある場合は、fragmentメソッドを使用できます。たとえば、各ページネーションリンクの末尾に#usersを追加するには、次のようにfragmentメソッドを呼び出す必要があります:

  1. $users = User::paginate(15)->fragment('users');

ページネーション結果の表示

  1. これらのオブジェクトは、結果セットを説明するいくつかのメソッドを提供します。これらのヘルパーメソッドに加えて、ページネーターインスタンスはイテレーターであり、配列としてループすることができます。したがって、結果を取得したら、結果を表示し、[Blade](/read/laravel-11-x/3aaaf25bb396ee8c.md)を使用してページリンクをレンダリングできます:
  2. ``````blade
  3. <div class="container">
  4. @foreach ($users as $user)
  5. {{ $user->name }}
  6. @endforeach
  7. </div>
  8. {{ $users->links() }}
  9. `

linksメソッドは、結果セット内の他のページへのリンクをレンダリングします。これらのリンクのそれぞれには、適切なpageクエリ文字列変数がすでに含まれています。linksメソッドによって生成されるHTMLは、Tailwind CSSフレームワークと互換性があることを忘れないでください。

ページネーションリンクウィンドウの調整

ページネーターがページネーションリンクを表示するとき、現在のページ番号と現在のページの前後3ページのリンクが表示されます。onEachSideメソッドを使用して、ページネーターによって生成されたリンクの中間スライディングウィンドウ内で、現在のページの両側に表示される追加のリンクの数を制御できます:

  1. {{ $users->onEachSide(5)->links() }}

結果をJSONに変換

LaravelのページネータークラスはIlluminate\Contracts\Support\Jsonableインターフェース契約を実装し、toJsonメソッドを公開しているため、ページネーション結果をJSONに変換するのは非常に簡単です。また、ルートまたはコントローラーアクションから返すことによって、ページネーターインスタンスをJSONに変換することもできます:

  1. use App\Models\User;
  2. Route::get('/users', function () {
  3. return User::paginate();
  4. });

ページネーターからのJSONには、totalcurrent_pagelast_pageなどのメタ情報が含まれます。結果レコードは、JSON配列内のdataキーを介して利用可能です。以下は、ルートからページネーターインスタンスを返すことによって作成されたJSONの例です:

  1. {
  2. "total": 50,
  3. "per_page": 15,
  4. "current_page": 1,
  5. "last_page": 4,
  6. "first_page_url": "http://laravel.app?page=1",
  7. "last_page_url": "http://laravel.app?page=4",
  8. "next_page_url": "http://laravel.app?page=2",
  9. "prev_page_url": null,
  10. "path": "http://laravel.app",
  11. "from": 1,
  12. "to": 15,
  13. "data":[
  14. {
  15. // Record...
  16. },
  17. {
  18. // Record...
  19. }
  20. ]
  21. }

ページネーションビューのカスタマイズ

デフォルトでは、ページネーションリンクを表示するためにレンダリングされるビューはTailwind CSSフレームワークと互換性があります。ただし、Tailwindを使用していない場合は、これらのリンクをレンダリングするために独自のビューを定義することができます。ページネーターインスタンスでlinksメソッドを呼び出すとき、メソッドの最初の引数としてビュー名を渡すことができます:

  1. {{ $paginator->links('view.name') }}
  2. <!-- Passing additional data to the view... -->
  3. {{ $paginator->links('view.name', ['foo' => 'bar']) }}

ただし、ページネーションビューをカスタマイズする最も簡単な方法は、resources/views/vendorディレクトリにvendor:publishコマンドを使用してエクスポートすることです:

  1. php artisan vendor:publish --tag=laravel-pagination

このコマンドは、アプリケーションのresources/views/vendor/paginationディレクトリにビューを配置します。このディレクトリ内のtailwind.blade.phpファイルは、デフォルトのページネーションビューに対応します。このファイルを編集してページネーションHTMLを変更できます。

デフォルトのページネーションビューとして異なるファイルを指定したい場合は、defaultViewおよびdefaultSimpleViewメソッドをbootクラスのApp\Providers\AppServiceProviderメソッド内で呼び出すことができます:

  1. <?php
  2. namespace App\Providers;
  3. use Illuminate\Pagination\Paginator;
  4. use Illuminate\Support\ServiceProvider;
  5. class AppServiceProvider extends ServiceProvider
  6. {
  7. /**
  8. * Bootstrap any application services.
  9. */
  10. public function boot(): void
  11. {
  12. Paginator::defaultView('view-name');
  13. Paginator::defaultSimpleView('view-name');
  14. }
  15. }

Bootstrapの使用

Laravelには、Bootstrap CSSを使用して構築されたページネーションビューが含まれています。これらのビューをデフォルトのTailwindビューの代わりに使用するには、useBootstrapFourまたはuseBootstrapFiveメソッドをbootクラスのApp\Providers\AppServiceProviderメソッド内で呼び出すことができます:

  1. use Illuminate\Pagination\Paginator;
  2. /**
  3. * Bootstrap any application services.
  4. */
  5. public function boot(): void
  6. {
  7. Paginator::useBootstrapFive();
  8. Paginator::useBootstrapFour();
  9. }

ページネーター / LengthAwarePaginatorインスタンスメソッド

各ページネーターインスタンスは、以下のメソッドを介して追加のページネーション情報を提供します:

メソッド 説明
$paginator->count() 現在のページのアイテム数を取得します。
$paginator->currentPage() 現在のページ番号を取得します。
$paginator->firstItem() 結果内の最初のアイテムの結果番号を取得します。
$paginator->getOptions() ページネーターオプションを取得します。
$paginator->getUrlRange($start, $end) ページネーションURLの範囲を作成します。
$paginator->hasPages() 複数ページに分割するのに十分なアイテムがあるかどうかを判断します。
$paginator->hasMorePages() データストアにさらにアイテムがあるかどうかを判断します。
$paginator->items() 現在のページのアイテムを取得します。
$paginator->lastItem() 結果内の最後のアイテムの結果番号を取得します。
$paginator->lastPage() 利用可能な最後のページのページ番号を取得します。(simplePaginateを使用している場合は利用できません)。
$paginator->nextPageUrl() 次のページのURLを取得します。
$paginator->onFirstPage() ページネーターが最初のページにいるかどうかを判断します。
$paginator->perPage() ページごとに表示されるアイテムの数。
$paginator->previousPageUrl() 前のページのURLを取得します。
$paginator->total() データストア内の一致するアイテムの総数を判断します。(simplePaginateを使用している場合は利用できません)。
$paginator->url($page) 指定されたページ番号のURLを取得します。
$paginator->getPageName() ページを保存するために使用されるクエリ文字列変数を取得します。
$paginator->setPageName($name) ページを保存するために使用されるクエリ文字列変数を設定します。
$paginator->through($callback) コールバックを使用して各アイテムを変換します。

カーソルページネーターインスタンスメソッド

各カーソルページネーターインスタンスは、以下のメソッドを介して追加のページネーション情報を提供します:

メソッド 説明
$paginator->count() 現在のページのアイテム数を取得します。
$paginator->cursor() 現在のカーソルインスタンスを取得します。
$paginator->getOptions() ページネーターオプションを取得します。
$paginator->hasPages() 複数ページに分割するのに十分なアイテムがあるかどうかを判断します。
$paginator->hasMorePages() データストアにさらにアイテムがあるかどうかを判断します。
$paginator->getCursorName() カーソルを保存するために使用されるクエリ文字列変数を取得します。
$paginator->items() 現在のページのアイテムを取得します。
$paginator->nextCursor() 次のアイテムセットのカーソルインスタンスを取得します。
$paginator->nextPageUrl() 次のページのURLを取得します。
$paginator->onFirstPage() ページネーターが最初のページにいるかどうかを判断します。
$paginator->onLastPage() ページネーターが最後のページにいるかどうかを判断します。
$paginator->perPage() ページごとに表示されるアイテムの数。
$paginator->previousCursor() 前のアイテムセットのカーソルインスタンスを取得します。
$paginator->previousPageUrl() 前のページのURLを取得します。
$paginator->setCursorName() カーソルを保存するために使用されるクエリ文字列変数を設定します。
$paginator->url($cursor) 指定されたカーソルインスタンスのURLを取得します。