はじめに
他のフレームワークでは、ページネーションは非常に面倒です。Laravelのページネーションのアプローチが新鮮な風になることを期待しています。Laravelのページネーターは、クエリビルダーとEloquent ORMに統合されており、ゼロ設定でデータベースレコードの便利で使いやすいページネーションを提供します。
デフォルトでは、ページネーターによって生成されるHTMLはTailwind CSSフレームワークと互換性がありますが、Bootstrapのページネーションサポートも利用可能です。
Tailwind JIT
LaravelのデフォルトのTailwindページネーションビューとTailwind JITエンジンを使用している場合は、アプリケーションのtailwind.config.js
ファイルのcontent
キーがLaravelのページネーションビューを参照していることを確認し、Tailwindクラスが削除されないようにしてください:
content: [
'./resources/**/*.blade.php',
'./resources/**/*.js',
'./resources/**/*.vue',
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
],
基本的な使用法
クエリビルダー結果のページネーション
アイテムをページネートする方法はいくつかあります。最も簡単なのは、クエリビルダーまたはEloquentクエリのpaginate
メソッドを使用することです。paginate
メソッドは、ユーザーが表示している現在のページに基づいてクエリの「制限」と「オフセット」を自動的に設定します。デフォルトでは、現在のページはHTTPリクエストのpage
クエリ文字列引数の値によって検出されます。この値はLaravelによって自動的に検出され、ページネーターによって生成されたリンクにも自動的に挿入されます。
この例では、paginate
メソッドに渡される唯一の引数は、「ページごとに表示したいアイテムの数」です。この場合、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)
]);
}
}
シンプルなページネーション
したがって、アプリケーションのUIにシンプルな「次へ」と「前へ」リンクのみを表示する必要がある場合は、`````simplePaginate`````メソッドを使用して単一の効率的なクエリを実行できます:
``````php
$users = DB::table('users')->simplePaginate(15);
`
Eloquent結果のページネーション
Eloquent[$3a3cc29cc73636fb.md]クエリもページネートできます。この例では、App\Models\User
モデルをページネートし、ページごとに15レコードを表示する予定であることを示します。ご覧のとおり、構文はクエリビルダー結果のページネーションとほぼ同じです:
use App\Models\User;
$users = User::paginate(15);
もちろん、paginate
メソッドを呼び出す前に、where
句などの他の制約をクエリに設定することができます:
$users = User::where('votes', '>', 100)->paginate(15);
Eloquentモデルをページネートする際にsimplePaginate
メソッドを使用することもできます:
$users = User::where('votes', '>', 100)->simplePaginate(15);
同様に、cursorPaginate
メソッドを使用してEloquentモデルをカーソルページネートすることもできます:
$users = User::where('votes', '>', 100)->cursorPaginate(15);
ページごとの複数のページネーターインスタンス
時には、アプリケーションによってレンダリングされる単一の画面に2つの別々のページネーターをレンダリングする必要がある場合があります。ただし、両方のページネーターインスタンスが現在のページを保存するためにpage
クエリ文字列パラメータを使用している場合、2つのページネーターが競合します。この競合を解決するには、paginate
、simplePaginate
、cursorPaginate
メソッドに提供される3番目の引数を介して、ページネーターの現在のページを保存するために使用したいクエリ文字列パラメータの名前を渡すことができます:
use App\Models\User;
$users = User::where('votes', '>', 100)->paginate(
$perPage = 15, $columns = ['*'], $pageName = 'users'
);
カーソルページネーション
オフセットベースのページネーションとは異なり、ページネーターによって生成されたURLのクエリ文字列にページ番号を含めるのではなく、カーソルベースのページネーションはクエリ文字列に「カーソル」文字列を配置します。カーソルは、次のページネートクエリがどこから開始すべきか、どの方向にページネートすべきかを示すエンコードされた文字列です:
``````nothing
http://localhost/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0
`
クエリビルダーが提供するcursorPaginate
メソッドを介してカーソルベースのページネーターインスタンスを作成できます。このメソッドはIlluminate\Pagination\CursorPaginator
のインスタンスを返します:
$users = DB::table('users')->orderBy('id')->cursorPaginate(15);
カーソルページネーターインスタンスを取得したら、通常のpaginate
およびsimplePaginate
メソッドを使用してページネーション結果を表示できます。カーソルページネーターが提供するインスタンスメソッドの詳細については、カーソルページネーターインスタンスメソッドのドキュメントを参照してください。
クエリには、カーソルページネーションを利用するために「order by」句が含まれている必要があります。また、クエリが順序付けられている列は、ページネートしているテーブルに属している必要があります。
カーソルとオフセットページネーション
オフセットページネーションとカーソルページネーションの違いを示すために、いくつかのSQLクエリの例を見てみましょう。以下の2つのクエリは、users
テーブルの「2ページ目」の結果を表示します。id
で順序付けられています:
# オフセットページネーション...
select * from users order by id asc limit 15 offset 15;
# カーソルページネーション...
select * from users where id
> 15 order by id asc limit 15;
カーソルページネーションクエリは、オフセットページネーションに対して以下の利点を提供します:
- 大規模なデータセットの場合、「order by」列がインデックスされていると、カーソルページネーションはより良いパフォーマンスを提供します。これは、「オフセット」句がすべての以前に一致したデータをスキャンするためです。
- 書き込みが頻繁なデータセットの場合、オフセットページネーションは、ユーザーが現在表示しているページに最近追加または削除された結果があると、レコードをスキップしたり重複を表示したりする可能性があります。
ただし、カーソルページネーションには以下の制限があります:
simplePaginate
のように、カーソルページネーションは「次へ」と「前へ」リンクを表示するためにのみ使用でき、ページ番号を持つリンクの生成をサポートしていません。- 少なくとも1つのユニークな列またはユニークな列の組み合わせに基づいて順序付けされる必要があります。
null
値を持つ列はサポートされていません。 - 「order by」句のクエリ式は、エイリアスが付けられ、選択句にも追加されている場合にのみサポートされます。
- パラメータを持つクエリ式はサポートされていません。
ページネーターの手動作成
時には、メモリ内にすでにあるアイテムの配列を渡してページネーションインスタンスを手動で作成したい場合があります。その場合、Illuminate\Pagination\Paginator
、Illuminate\Pagination\LengthAwarePaginator
、またはIlluminate\Pagination\CursorPaginator
インスタンスを作成できます。
言い換えれば、`````Paginator`````はクエリビルダーの`````simplePaginate`````メソッドに対応し、`````CursorPaginator`````は`````cursorPaginate`````メソッドに対応し、`````LengthAwarePaginator`````は`````paginate`````メソッドに対応します。
ページネーターインスタンスを手動で作成する際は、ページネーターに渡す結果の配列を手動で「スライス」する必要があります。これを行う方法がわからない場合は、[array_slice](https://secure.php.net/manual/en/function.array-slice.php) PHP関数を確認してください。
<a name="customizing-pagination-urls"></a>
### ページネーションURLのカスタマイズ
デフォルトでは、ページネーターによって生成されるリンクは、現在のリクエストのURIに一致します。ただし、ページネーターの`````withPath`````メソッドを使用すると、リンクを生成する際にページネーターが使用するURIをカスタマイズできます。たとえば、ページネーターに`````http://example.com/admin/users?page=N`````のようなリンクを生成させたい場合は、`````/admin/users`````を`````withPath`````メソッドに渡す必要があります:
``````php
use App\Models\User;
Route::get('/users', function () {
$users = User::paginate(15);
$users->withPath('/admin/users');
// ...
});
`
クエリ文字列値の追加
ページネーションリンクのクエリ文字列に追加するには、appends
メソッドを使用できます。たとえば、各ページネーションリンクにsort=votes
を追加するには、appends
に次の呼び出しを行う必要があります:
use App\Models\User;
Route::get('/users', function () {
$users = User::paginate(15);
$users->appends(['sort' => 'votes']);
// ...
});
現在のリクエストのすべてのクエリ文字列値をページネーションリンクに追加したい場合は、withQueryString
メソッドを使用できます:
$users = User::paginate(15)->withQueryString();
ハッシュフラグメントの追加
ページネーターによって生成されたURLに「ハッシュフラグメント」を追加する必要がある場合は、fragment
メソッドを使用できます。たとえば、各ページネーションリンクの末尾に#users
を追加するには、次のようにfragment
メソッドを呼び出す必要があります:
$users = User::paginate(15)->fragment('users');
ページネーション結果の表示
これらのオブジェクトは、結果セットを説明するいくつかのメソッドを提供します。これらのヘルパーメソッドに加えて、ページネーターインスタンスはイテレーターであり、配列としてループすることができます。したがって、結果を取得したら、結果を表示し、[Blade](/read/laravel-11-x/3aaaf25bb396ee8c.md)を使用してページリンクをレンダリングできます:
``````blade
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
`
links
メソッドは、結果セット内の他のページへのリンクをレンダリングします。これらのリンクのそれぞれには、適切なpage
クエリ文字列変数がすでに含まれています。links
メソッドによって生成されるHTMLは、Tailwind CSSフレームワークと互換性があることを忘れないでください。
ページネーションリンクウィンドウの調整
ページネーターがページネーションリンクを表示するとき、現在のページ番号と現在のページの前後3ページのリンクが表示されます。onEachSide
メソッドを使用して、ページネーターによって生成されたリンクの中間スライディングウィンドウ内で、現在のページの両側に表示される追加のリンクの数を制御できます:
{{ $users->onEachSide(5)->links() }}
結果をJSONに変換
LaravelのページネータークラスはIlluminate\Contracts\Support\Jsonable
インターフェース契約を実装し、toJson
メソッドを公開しているため、ページネーション結果をJSONに変換するのは非常に簡単です。また、ルートまたはコントローラーアクションから返すことによって、ページネーターインスタンスをJSONに変換することもできます:
use App\Models\User;
Route::get('/users', function () {
return User::paginate();
});
ページネーターからのJSONには、total
、current_page
、last_page
などのメタ情報が含まれます。結果レコードは、JSON配列内のdata
キーを介して利用可能です。以下は、ルートからページネーターインスタンスを返すことによって作成された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...
}
]
}
ページネーションビューのカスタマイズ
デフォルトでは、ページネーションリンクを表示するためにレンダリングされるビューはTailwind CSSフレームワークと互換性があります。ただし、Tailwindを使用していない場合は、これらのリンクをレンダリングするために独自のビューを定義することができます。ページネーターインスタンスでlinks
メソッドを呼び出すとき、メソッドの最初の引数としてビュー名を渡すことができます:
{{ $paginator->links('view.name') }}
<!-- Passing additional data to the view... -->
{{ $paginator->links('view.name', ['foo' => 'bar']) }}
ただし、ページネーションビューをカスタマイズする最も簡単な方法は、resources/views/vendor
ディレクトリにvendor:publish
コマンドを使用してエクスポートすることです:
php artisan vendor:publish --tag=laravel-pagination
このコマンドは、アプリケーションのresources/views/vendor/pagination
ディレクトリにビューを配置します。このディレクトリ内のtailwind.blade.php
ファイルは、デフォルトのページネーションビューに対応します。このファイルを編集してページネーションHTMLを変更できます。
デフォルトのページネーションビューとして異なるファイルを指定したい場合は、defaultView
およびdefaultSimpleView
メソッドをboot
クラスのApp\Providers\AppServiceProvider
メソッド内で呼び出すことができます:
<?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を使用して構築されたページネーションビューが含まれています。これらのビューをデフォルトのTailwindビューの代わりに使用するには、useBootstrapFour
またはuseBootstrapFive
メソッドをboot
クラスのApp\Providers\AppServiceProvider
メソッド内で呼び出すことができます:
use Illuminate\Pagination\Paginator;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Paginator::useBootstrapFive();
Paginator::useBootstrapFour();
}
ページネーター / 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を取得します。 |