イントロダクション
他のフレームワークのペジネーションは苦痛に満ちています。LaravelのペジネータはクエリビルダとEloquent ORMに統合されており、データベースの結果を簡単、お手軽にペジネーションできます。ペジネータが生成するHTMLは、Bootstrap CSSフレームワークコンパチブルです。
基本的な使用法
クエリビルダの結果
アイテムをペジネーションするには多くの方法があります。一番簡単な方法は、クエリビルダとEloquent
queryへpaginate
メソッドを使う方法です。paginate
メソッドは、ユーザーが表示している現在のページに基づき、正しいアイテム数とオフセットを指定する面倒を見ます。デフォルトではHTTPリクエストのpage
クエリ文字列引数の値により現在ページが決められます。この値はLaravelが自動的に探し、さらにペジネーターが挿入するリンクを自動的に生成します。
以下の例では、paginate
に一つだけ引数を渡しており、「ページごと」に表示したいアイテム数です。この例ではページごとに15
アイテムを表示するように指定しています。
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* アプリケーションの全ユーザー表示
*
* @return Response
*/
public function index()
{
$users = DB::table('users')->paginate(15);
return view('user.index', ['users' => $users]);
}
}
Note: 現在
groupBy
文を使用したペジネーション操作は、Laravelで効率よく実行できません。groupBy
を使用したペジネーションを使用する必要がある場合はデータベースクエリを実行し、その結果を元にペジネーターを自前で作成してください。
シンプル・ペジネーション
「次」と「前」のリンクだけのシンプルなペジネーションビューを表示したい場合はsimplePaginate
メソッドを使用し、より効率的にクエリすべきでしょう。これはビューに正確なページ番号を表示する必要がない、巨大なデータセットを扱う場合に便利です。
$users = DB::table('users')->simplePaginate(15);
Eloquentの結果
さらにEloquentモデルもペジネーションできます。例としてUser
モデルの15
アイテムをページ付け表示してみましょう。ご覧の通り、クエリビルダ結果のペジネーションを行う記法はきれいでわかりやすいものです。
$users = App\User::paginate(15);
where
節のような制約をクエリに指定した後に、paginate
を呼び出すこともできます。
$users = User::where('votes', '>', 100)->paginate(15);
Elqouentモデルをページづけするときにも、simplePaginate
メソッドを使用できます。
$users = User::where('votes', '>', 100)->simplePaginate(15);
独自ペジネータ作成
渡された配列を元にして、ペジネーションインスンタンスを作成したいこともあります。必要に応じてIlluminate\Pagination\Paginator
か、Illuminate\Pagination\LengthAwarePaginator
インスタンスを生成することで実現できます。
Paginator
クラスは結果にセットされているアイテムの総数を知る必要はありません。そのためクラスは最終ページのインデックスを取得するメソッドを持っていません。LengthAwarePaginator
はPaginator
とほとんど同じ引数を取りますが、結果にセットされているアイテム総数も指定する必要がある点が異なっています。
言い換えれば、Paginator
はクエリビルダとEloquentに対するsimplePaginate
メソッドに対応し、一方のLengthAwarePaginator
はpaginate
に対応しています。
Note: 自前でペジネーターインスタンスを生成する場合、ペジネーターに渡す結果の配列を自分で"slice"する必要があります。その方法を思いつかなければ、array_slice PHP関数を調べてください。
ペジネーション結果の表示
paginate
メソッドを呼び出す場合、Illuminate\Pagination\LengthAwarePaginator
インスタンスを受け取ります。simplePaginate
メソッドを呼び出すときは、Illuminate\Pagination\Paginator
インスタンスを受け取ります。これらのオブジェクトは結果を表すたくさんのメソッドを提供しています。こうしたヘルパメソッドに加え、ペジネーターインスタンスはイテレータでもあり、配列としてループ処理できます。つまり結果を取得したら、その結果とページリンクをBladeを使い表示できます。
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
links
メソッドは結果の残りのページヘのリンクをレンダーします。それらの各リンクにはpage
クエリ文字列変数が含まれています。links
メソッドが生成するHTMLはBootstrap
CSSフレームワークと互換性があることを覚えておいてください。
ペジネーターURIのカスタマイズ
withPath
メソッドにより、ペジネーターがリンクを生成するときに使用するURIをカスタマイズできます。たとえばペジネーターでhttp://example.com/custom/url?page=N
のようなリンクを生成したい場合、withPath
メソッドにcustom/url
を渡してください。
Route::get('users', function () {
$users = App\User::paginate(15);
$users->withPath('custom/url');
//
});
ペジネーションリンクの追加
ペジネーションリンクにクエリ文字列を付け加えたいときは、appends
メソッドを使います。たとえばsort=votes
を各ペジネーションリンクに追加する場合には、以下のようにappends
を呼び出します。
{{ $users->appends(['sort' => 'votes'])->links() }}
ペジネーションのURLに「ハッシュフラグメント」を追加したい場合は、fragment
メソッドが使用できます。例えば各ペジネーションリンクの最後に#foo
を追加したい場合は、以下のようにfragment
メソッドを呼び出します。
{{ $users->fragment('foo')->links() }}
ペジネーションリンクウィンドウの調整
ペギネータのURL「ウィンドウ」の両サイドに、いくつの追加のリンクを表示するかを調整できます。デフォルトでは、メインのペジネータリンクの両サイドに3つのリンクが表示されます。この数を調整するには、onEachSide
メソッドを使用します。
{{ $users->onEachSide(5)->links() }}
結果のJSON変換
Laravelのペジネーター結果クラスはIlluminate\Contracts\Support\Jsonable
インターフェイス契約を実装しており、toJson
メソッドを提示しています。ですからペジネーション結果をJSONにとても簡単に変換できます。またルートやコントローラアクションからペジネーターインスタンスを返せば、JSONへ変換されます。
Route::get('users', function () {
return App\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":[
{
// 結果のオブジェクト
},
{
// 結果のオブジェクト
}
]
}
ペジネーションビューのカスタマイズ
デフォルトで、ペジネーションリンクを表示するためのビューはBootstrap
CSSフレームワークを用いてレンダーされます。しかし、Bootstrapを使っていない場合でも、そうしたリンクをレンダーする独自のビューを自由に定義できます。ペジネータインスタンスのlinks
メソッドを呼び出す際に、ビュー名をメソッドの最初の引数として渡してください。
{{ $paginator->links('view.name') }}
// ビューへデータを渡す
{{ $paginator->links('view.name', ['foo' => 'bar']) }}
しかし、vendor:publish
コマンドを使用し、resources/views/vendor
ディレクトリへペジネーションビューを作成し、カスタマイズする方法が一番簡単でしょう。
php artisan vendor:publish --tag=laravel-pagination
このコマンドは、resources/views/vendor/pagination
ディレクトリへビューを設置します。このディレクトリのbootstrap-4.blade.php
ファイルが、デフォルトのペジネーションビューに当ります。ペジネーションHTMLを変更するために、このファイルを編集できます。
デフォルトのペジネーションビューとして、他のファイルを指定したい場合は、AppServiceProvider
の中で、ペジネータのdefaultView
とdefaultSimpleView
メソッドを使用します。
use Illuminate\Pagination\Paginator;
public function boot()
{
Paginator::defaultView('view-name');
Paginator::defaultSimpleView('view-name');
}
ペジネータインスタンスメソッド
ペジネータインスタンスは以下の追加ペジネーション情報を提供しています。
メソッド | 説明 |
---|---|
$results->count() |
現在のページのアイテム数取得 |
$results->currentPage() |
現在のページ数 |
$results->firstItem() |
現在ページの最初のアイテムが何番目か取得 |
$results->getOptions() |
ペジネータオプション取得 |
$results->getUrlRange($start, $end) |
一定範囲のペジネーションURLを取得 |
$results->hasMorePages() |
複数ページへアイテムを分割できる数があるか判定 |
$results->lastItem() |
現在ページの最後のアイテムが何番目か取得 |
$results->lastPage() |
利用可能な最終ページ数取得(simplePaginate では使用できない) |
$results->nextPageUrl() |
次ページのURL取得 |
$results->onFirstPage() |
ペジネータが最初のページを扱っているか判定 |
$results->perPage() |
ページごとに表示するアイテム数 |
$results->previousPageUrl() |
前ページのURL取得 |
$results->total() |
データ領域にある、条件に一致するアイテムの総数(simplePaginate では使用できない) |
$results->url($page) |
指定したページのURL取得 |