Lang x Lang

Database: Pagination

Table of Contents

Introduction

他のフレームワークでは、 pagination は非常に困難な作業になることがあります。それに対し、Laravel の pagination アプローチは新鮮な息吹を提供することでしょう。Laravel の paginator は、query builderEloquent ORMと統合されており、設定不要で database レコードの pagination を簡単に、便利に提供します。

default として、 paginator が生成する HTML はTailwind CSS フレームワーク と互換性があります。ただし、ブートストラップの pagination サポートも利用可能です。

Tailwind JIT

もし Laravel の default な Tailwind の pagination views と Tailwind JIT エンジンを使用している場合、tailwind.config.js ファイルの content キーが Laravel の pagination views を参照するように、アプリケーションを確認すべきです。それにより、その Tailwind クラスはパージされないでしょう:

content: [
    './resources/**/*.blade.php',
    './resources/**/*.js',
    './resources/**/*.vue',
    './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
],

Basic Usage

Query ビルダー結果のページネーション

いくつかの方法があります。最も簡単な方法は、query ビルダーエロキュアント querypaginatemethod を使用することです。paginatemethod は、現在 user が閲覧しているページに基づいて、自動的に query の"limit"と"offset"を設定します。default では、現在のページは HTTP request のpagequery ストリング引数の value によって検出されます。この value は Laravel によって自動的に検出され、また、生成される links に自動的に挿入されます。

この例では、paginate method に渡される唯一の引数は、"ページあたり"に表示したいアイテムの数です。この場合、1 ページあたり15項目を表示したいと指定しましょう。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * Show all application users.
     */
    public function index(): View
    {
        return view('user.index', [
            'users' => DB::table('users')->paginate(15)
        ]);
    }
}

シンプルな Pagination

paginate method は、レコードを database から取得する前に、 query によって一致したレコードの総数を数えます。これは、 paginator がレコードのページ数を合計でどれだけあるかを知るために行われます。しかし、アプリケーションの UI で総ページ数を表示する予定がないなら、レコード数を数える query は必要ありません。

したがって、あなたが application の UI で単純な "Next" と "Previous" links だけを表示する必要がある場合は、simplePaginate method を使って、 single , 効率的な query を実行することができます。

$users = DB::table('users')->simplePaginate(15);

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

あなたはまた、Eloquentのクエリをページ分割することもできます。この例では、App\Models\User model をページ分割し、1 ページあたり 15 レコードを表示する予定であることを示します。ご覧の通り、構文は、query ビルダーの結果をページ分割するのとほぼ同一です。

use App\Models\User;

$users = User::paginate(15);

もちろん、他の制約をwhere句のような query に設定した後で、paginate method を呼び出すことができます。

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

また、simplePaginateの method を使用して Eloquent models をページネーションすることも可能です:

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

同様に、cursorPaginate method を使用して、 cursor paginate Eloquent models を行うことができます。

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

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

時には、あなたの application によって rendering された single 画面上で 2 つの別々の paginator を render する必要があるかもしれません。ただし、両方の paginator インスタンスが現在のページを保存するために page query string パラメータを使用すると、2 つの paginator が競合します。この競合を解決するために、paginator の現在のページを保存するために使用したい query string パラメータの名前を、 paginatesimplePaginate、そして cursorPaginate method へ提供された第 3 引数を通して指定することができます。

use App\Models\User;

$users = User::where('votes', '>', 100)->paginate(
    $perPage = 15, $columns = ['*'], $pageName = 'users'
);

Cursor Pagination

paginatesimplePaginateは、SQL の"offset"句を使用してクエリを作成しますが、 cursor pagination は、"where"句を作成して query に含まれる並べ替えられた列の values を比較し、Laravel の全ての pagination メソッドの中で最も効率的な database パフォーマンスを提供します。この pagination の method は、大量のデータセットや無限スクロールの user インターフェースに特に適しています。

オフセットベースの pagination は、URL の query string にページ番号を含むのに対して、 paginator ベースの pagination は、 query string に cursor の string を配置します。 cursor は、次のページネーションされた query が開始するべき場所と、それが paginate するべき方向を含むエンコードされた string です。

http://localhost/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0

cursorPaginate method を使用して、 query ビルダーが提供する cursor ベースの paginator インスタンスを作成することができます。この method は、Illuminate\Pagination\CursorPaginatorのインスタンスを返します。

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

cursor paginator インスタンスを取得したら、通常paginatesimplePaginateメソッドを使用するときと同じように、ページネーション結果を表示することができます。 cursor paginator が提供するインスタンスメソッドの詳細については、cursor paginator インスタンスの method ドキュメンテーションをご参照ください。

WARNING

あなたの query は、 cursor pagination を活用するためには"order by"句を含める必要があります。さらに、" query "が並べ替えるカラムは、ページングしているテーブルに所属している必要があります。

Cursor vs. オフセット Pagination

offset ページネーションと cursor ページネーションの違いを図示するために、いくつかの SQLqueries の例を見てみましょう。次の両方の queries は、idで並べ替えられたusersテーブルの結果の 2 ページ目を表示します。

# Offset Pagination...
select * from users order by id asc limit 15 offset 15;

# Cursor Pagination...
select * from users where id > 15 order by id asc limit 15;

cursor pagination query はオフセット pagination に対して次のような利点を提供します:

  • 大規模なデータセットに対しては、 cursor pagination が order by 列がインデックス化されている場合には、より良いパフォーマンスを提供します。これは、offset 句が以前に一致した data すべてをスキャンするためです。
  • 頻繁に書き込みが行われるデータセットの場合、オフセットの pagination は、結果が最近ページに追加されたり、ページから削除された場合、 user が現在閲覧しているページでレコードを skip したり、重複を表示する場合があります。

ただし、 cursor pagination には以下の制限があります:

  • simplePaginateのように、 cursor pagination は次および前の links の表示のみに使用でき、ページ番号付きの links の生成をサポートしていません。
  • 順序付けは、少なくとも一つの unique column または unique な列の組み合わせに基づいていることが必要です。nullの values が含まれる列はサポートされていません。
  • "order by"句内の Query 式は、エイリアスが付けられ、"select"句に追加されている場合にのみサポートされます。
  • パラメータを含む Query 式はサポートされていません。

手動で Paginator を作成する

時々、メモリにすでに持っている array のアイテムを渡して、手動で pagination インスタンスを作成したい場合があります。それは、Illuminate\Pagination\PaginatorIlluminate\Pagination\LengthAwarePaginator、または Illuminate\Pagination\CursorPaginator インスタンスを作成することにより、あなたのニーズに応じて行うことができます。

PaginatorおよびCursorPaginatorクラスは、結果セット内のアイテムの総数を知る必要はありません。しかし、そのため、これらのクラスには最後のページのインデックスを取得するメソッドがありません。LengthAwarePaginatorは、Paginatorとほぼ同じ引数を受け入れますが、結果セット内のアイテムの総数を数える必要があります。

つまり、Paginatorは query ビルダーのsimplePaginate method に対応し、CursorPaginatorcursorPaginate method に対応し、LengthAwarePaginatorpaginate method に対応します。

WARNING

手動で paginator インスタンスを作成するときは、paginator に渡す結果の array を手動で"スライス"する必要があります。 これがどのように行うかわからない場合は、 array_slice PHP 関数を確認してください。

Pagination URL のカスタマイズ

デフォルトでは、 default によって生成される links は、現在のリクエストの URI と match します。しかし、 paginator の withPath method は、 paginator が links を生成する際に使用する URI をカスタマイズすることができます。例えば、 paginator に http://example.com/admin/users?page=Nのような links を生成させたい場合、withPath method に /admin/users を渡す必要があります。

use App\Models\User;

Route::get('/users', function () {
    $users = User::paginate(15);

    $users->withPath('/admin/users');

    // ...
});

Query String Values の追加

appends を使用して、ページング links の querystring に 追加できます。例えば、各ページング links に sort=votesを 追加するには、appendsに次のように呼び出しを行うべきです:

use App\Models\User;

Route::get('/users', function () {
    $users = User::paginate(15);

    $users->appends(['sort' => 'votes']);

    // ...
});

withQueryStringmethod を使用すると、現在の request の querystring の values をすべてページネーション link に追加することができます:

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

Hash フラグメントの追加

paginator によって生成された URL に "hash fragment" を追加する必要がある場合は、fragment method を使用できます。たとえば、各 pagination リンクの末尾に #users を追加するには、次のように fragment method を呼び出す必要があります:

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

Displaying Pagination Results

paginate method を呼び出すと、Illuminate\Pagination\LengthAwarePaginatorのインスタンスが返されます。一方、simplePaginate method を呼び出すと、Illuminate\Pagination\Paginatorのインスタンスが返されます。そして最後に、cursorPaginate method を呼び出すと、Illuminate\Pagination\CursorPaginatorのインスタンスが返されます。

これらのオブジェクトは、結果セットを説明するいくつかのメソッドを提供します。これらのヘルパーメソッドに加えて、 paginator のインスタンスはイテレータであり、 array としてループすることができます。したがって、結果を retrieved したら、結果を表示し、ページの links をBladeを用いて render することができます。

<div class="container">
    @foreach ($users as $user)
        {{ $user->name }}
    @endforeach
</div>

{{ $users->links() }}

linksmethod は、結果セット内の他のページへの links を rendering します。これらの links のそれぞれは、すでに適切な page query ストリング variables を含んでいます。linksmethod によって生成された HTML は、Tailwind CSS フレームワーク と互換性があることを覚えておいてください。

Pagination リンクウィンドウの調整

paginator が pagination links を表示するとき、現在のページ番号だけでなく、現在のページの前後 3 ページの links も表示されます。onEachSide method を使うと、 paginator によって生成された links の中央、スライディングウィンドウの現在のページの両側に、何個の追加の links `を表示するかを制御できます。

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

結果を JSON に変換する

Laravel paginator classes はIlluminate\Contracts\Support\Jsonableインターフェース契約を実装し、toJson method を公開しているため、 pagination の結果を JSON に変換するのは非常に簡単です。また、 route や controller action から paginator インスタンスを返すことで、それを JSON に変換することもできます。

use App\Models\User;

Route::get('/users', function () {
    return User::paginate();
});

paginator からの JSON array には、totalcurrent_pagelast_pageなどの meta 情報が含まれます。結果レコードは JSON 配列のdataキーを介して利用できます。以下は、 route から paginator インスタンスを返すことで作成される JSON の例です:

{
   "total": 50,
   "per_page": 15,
   "current_page": 1,
   "last_page": 4,
   "first_page_url": "http://laravel.app?page=1",
   "last_page_url": "http://laravel.app?page=4",
   "next_page_url": "http://laravel.app?page=2",
   "prev_page_url": null,
   "path": "http://laravel.app",
   "from": 1,
   "to": 15,
   "data":[
        {
            // Record...
        },
        {
            // Record...
        }
   ]
}

Customizing the Pagination View

default では、ページネーションの links を表示するために rendering される views はTailwind CSS フレームワークと互換性があります。しかし、Tailwind を使用していない場合、自由に自分の views を定義してこれらの links を rendering することができます。linksmethod をページネーターのインスタンスで呼び出す際には、views の名前を method の最初の引数として渡すことができます。

{{ $paginator->links('view.name') }}

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

ただし、 pagination views をカスタマイズする最も簡単な方法は、vendor:publish command を使用してこれらをresources/views/vendorディレクトリにエクスポートすることです:

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

この command は、アプリケーションの resources/views/vendor/pagination ディレクトリに views を配置します。このディレクトリ内の tailwind.blade.php ファイルは、 default pagination view に対応しています。このファイルを編集して pagination HTML を変更することができます。

異なるファイルを default のページネーション view として指定したい場合、App\Providers\AppServiceProviderの method であるboot内で、paginator のdefaultViewdefaultSimpleViewmethod を呼び出すことができます:

<?php

namespace App\Providers;

use Illuminate\Pagination\Paginator;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Paginator::defaultView('view-name');

        Paginator::defaultSimpleView('view-name');
    }
}

Bootstrap の使用

Laravel には Bootstrap CSS を使用して構築された pagination views が含まれています。これらの views をデフォルトの Tailwind views の代わりに使用するには、App\Providers\AppServiceProvider class の boot method 内で paginator の useBootstrapFour または useBootstrapFive method を呼び出すことができます:

use Illuminate\Pagination\Paginator;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Paginator::useBootstrapFive();
    Paginator::useBootstrapFour();
}

Paginator / LengthAwarePaginator Instance Methods

各々の paginator インスタンスは、以下のメソッドを通じて追加の pagination 情報を提供します:

MethodDescription
$paginator->count()現在のページのアイテム数を取得します。
$paginator->currentPage()現在のページ番号を取得します。
$paginator->firstItem()結果の最初のアイテムの結果番号を取得します。
$paginator->getOptions()ページネータの option を取得します。
$paginator->getUrlRange($start, $end)pagination の URL の範囲を作成します。
$paginator->hasPages()複数のページに split するための十分なアイテムがあるかどうかを判断します。
$paginator->hasMorePages()data ストアにさらなるアイテムがあるかどうかを判断します。
$paginator->items()現在のページの項目を取得します。
$paginator->lastItem()結果の中で最後のアイテムの結果番号を取得します。
$paginator->lastPage()最後の利用可能なページのページ番号を取得します。(simplePaginateを使用している場合は利用できません)。
$paginator->nextPageUrl()次のページの URL を取得します。
$paginator->onFirstPage()paginator が最初のページにあるかどうかを決定します。
$paginator->perPage()ページごとに表示するアイテムの数。
$paginator->previousPageUrl()前のページの URL を取得します。
$paginator->total()data ストア内のマッチングアイテムの総数を決定します。(simplePaginateを使用している場合は利用できません)。
$paginator->url($page)指定されたページ番号の URL を取得します。
$paginator->getPageName()ページの保存に使用される query string 変数を取得します。
$paginator->setPageName($name)ページを保存するために使用する query string 変数を設定します。
$paginator->through($callback)各アイテムをコールバックを使用して Transform します。

Cursor Paginator Instance Methods

各々の cursor paginator インスタンスは、以下の方法を通じて追加の pagination 情報を提供します:

MethodDescription
$paginator->count()現在のページのアイテム数を取得します。
$paginator->cursor()現在の cursor インスタンスを取得します。
$paginator->getOptions()ページネータの option を取得します。
$paginator->hasPages()複数のページに split するのに十分なアイテムがあるかどうかを判断します。
$paginator->hasMorePages()data ストアにさらにアイテムがあるかどうかを決定します。
$paginator->getCursorName()cursor を保存するために使用される query string variable を取得します。
$paginator->items()現在のページのアイテムを取得します。
$paginator->nextCursor()次のアイテムセットのための cursor インスタンスを取得します。
$paginator->nextPageUrl()次のページの URL を取得します。
$paginator->onFirstPage()paginator が最初のページにあるかどうかを決定します。
$paginator->onLastPage()paginator が最後のページにあるかどうかを判断します。
$paginator->perPage()ページごとに表示するアイテムの数。
$paginator->previousCursor()前のアイテムセットの cursor インスタンスを取得します。
$paginator->previousPageUrl()前のページの URL を取得します。
$paginator->setCursorName()query string variable を設定して、 cursor を保存します。
$paginator->url($cursor)与えられた cursor インスタンスの URL を取得します。

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use