メインコンテンツへスキップ

Documentation Index

Fetch the complete documentation index at: https://kawax.biz/llms.txt

Use this file to discover all available pages before exploring further.

ページネーションとは

Laravelのページネーションは、クエリビルダーおよびEloquent ORMと統合されており、設定なしで使い始めることができます。現在のページはHTTPリクエストの page クエリパラメーターから自動的に取得され、生成されたリンクにも自動で付加されます。 デフォルトのHTMLはTailwind CSSに対応しており、Bootstrap CSSも選択できます。

3種類のページネーション

メソッド返り値特徴
paginate()LengthAwarePaginator総件数を取得。ページ番号リンクを生成
simplePaginate()Paginator総件数を取得しない。「前へ」「次へ」のみ
cursorPaginate()CursorPaginatorカーソルベース。大量データに最適

基本的な使い方

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

use Illuminate\Support\Facades\DB;

// 1ページあたり15件で取得
$users = DB::table('users')->paginate(15);

Eloquentのページネーション

use App\Models\User;

$users = User::paginate(15);

// 条件付き
$users = User::where('votes', '>', 100)->paginate(15);

simplePaginate

総件数のカウントクエリが不要な場合(「前へ」「次へ」リンクのみ表示)は simplePaginate() を使うと効率的です。
$users = DB::table('users')->simplePaginate(15);
$users = User::where('active', true)->simplePaginate(15);
「全部で何件中何件目」という表示が不要なら simplePaginate() を選びましょう。paginate()COUNT(*) クエリを追加で実行するため、simplePaginate() の方が高速です。

cursorPaginate(カーソルページネーション)

カーソルページネーションはOFFSET句の代わりにWHERE句を使うため、大量データに対して高いパフォーマンスを発揮します。無限スクロールのUIに特に適しています。
// orderBy が必須
$users = DB::table('users')->orderBy('id')->cursorPaginate(15);
$users = User::where('active', true)->cursorPaginate(15);
生成されるURLにはページ番号ではなくカーソル文字列が入ります。
http://example.com/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0
カーソルページネーションを使うには orderBy が必須です。また、並び順のカラムはページネーション対象のテーブルに属している必要があります。

OFFSETとカーソルの比較

-- paginate() / simplePaginate() — OFFSETを使う
SELECT * FROM users ORDER BY id ASC LIMIT 15 OFFSET 15;

-- cursorPaginate() — WHERE句を使う(インデックスが効く)
SELECT * FROM users WHERE id > 15 ORDER BY id ASC LIMIT 15;
カーソルページネーションはインデックスが有効活用され、データが頻繁に追加・削除される場合もレコードの重複・欠落が起きにくいという利点があります。ただし、ページ番号リンクの生成はできず、「前へ」「次へ」のみです。

コントローラーでの実装

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\View\View;

class UserController extends Controller
{
    public function index(): View
    {
        $users = User::orderBy('name')->paginate(20);

        return view('users.index', compact('users'));
    }
}

Bladeでのページネーションリンク表示

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

{{-- ページネーションリンクを出力(Tailwind CSS対応) --}}
{{ $users->links() }}
links() メソッドが自動でページリンクのHTMLを生成します。現在のページの前後3ページ分のリンクが表示されます。

表示するリンク数の調整

onEachSide() で現在のページの前後に表示するリンク数を変更できます。
{{-- 現在ページの前後5ページ分を表示 --}}
{{ $users->onEachSide(5)->links() }}

1ページあたりの件数をリクエストから受け取る

public function index(Request $request): View
{
    $perPage = $request->integer('per_page', 15);
    $perPage = min(max($perPage, 1), 100); // 1〜100の範囲に制限

    $users = User::paginate($perPage);

    return view('users.index', compact('users'));
}

1ページに複数のページネーターを表示する

同一画面に2つのページネーターを表示する場合、両方が page パラメーターを使うと競合します。第3引数でパラメーター名を変更します。
$users = User::paginate(
    perPage: 15,
    columns: ['*'],
    pageName: 'users'
);

$posts = Post::paginate(
    perPage: 10,
    columns: ['*'],
    pageName: 'posts'
);

URLのカスタマイズ

ベースURLの変更

$users = User::paginate(15);

// /admin/users?page=N 形式のURLを生成
$users->withPath('/admin/users');

クエリパラメーターの追加

// sort=votes を各ページリンクに追加
$users->appends(['sort' => 'votes']);

// 現在のリクエストの全クエリパラメーターを引き継ぐ
$users->withQueryString();

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

// URLの末尾に #users を追加
$users->fragment('users');

APIレスポンス(JSON出力)

ページネーターをルートやコントローラーからそのまま返すと、自動的にJSONに変換されます。
use App\Models\User;

Route::get('/api/users', function () {
    return User::paginate(15);
});
レスポンスのJSON形式:
{
    "total": 50,
    "per_page": 15,
    "current_page": 1,
    "last_page": 4,
    "first_page_url": "http://example.com/api/users?page=1",
    "last_page_url": "http://example.com/api/users?page=4",
    "next_page_url": "http://example.com/api/users?page=2",
    "prev_page_url": null,
    "path": "http://example.com/api/users",
    "from": 1,
    "to": 15,
    "data": [
        { "id": 1, "name": "山田太郎" },
        { "id": 2, "name": "鈴木花子" }
    ]
}

APIリソースとの組み合わせ

paginate() の結果をAPIリソースコレクションでラップする場合は UserResource::collection() に渡します。
use App\Http\Resources\UserResource;
use App\Models\User;

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

    return UserResource::collection($users);
});
UserResource::collection() にページネーターを渡すと、ページネーション情報がメタデータとして自動で付加されます。
cursorPaginate() のJSONにはページ番号ではなく next_cursorprev_cursor が含まれます。APIクライアントはこれらの値を次のリクエストの cursor パラメーターとして使います。

カスタムページネーションビュー

ビューファイルに直接指定

{{-- カスタムビューでリンクを出力 --}}
{{ $paginator->links('vendor.pagination.custom') }}

{{-- データを追加で渡す --}}
{{ $paginator->links('vendor.pagination.custom', ['theme' => 'dark']) }}

デフォルトビューをカスタムファイルに変更

まず公式のビューを公開してからカスタマイズします。
php artisan vendor:publish --tag=laravel-pagination
resources/views/vendor/pagination/ に以下のファイルが生成されます。
  • tailwind.blade.php — デフォルト(Tailwind CSS用)
  • bootstrap-5.blade.php — Bootstrap 5用
  • simple-tailwind.blade.php — simplePaginate用
tailwind.blade.php を直接編集するか、新しいビューを作成して AppServiceProvider で指定します。
use Illuminate\Pagination\Paginator;

public function boot(): void
{
    Paginator::defaultView('vendor.pagination.custom');
    Paginator::defaultSimpleView('vendor.pagination.simple-custom');
}

Bootstrap CSSを使う

TailwindではなくBootstrapを使う場合は AppServiceProviderboot() で指定します。
use Illuminate\Pagination\Paginator;

public function boot(): void
{
    Paginator::useBootstrapFive(); // Bootstrap 5
    // Paginator::useBootstrapFour(); // Bootstrap 4
}

手動でページネーターを作成する

配列などの既存データにページネーションを適用したい場合、ページネータークラスを直接インスタンス化します。
use Illuminate\Pagination\LengthAwarePaginator;

$items = collect(range(1, 200))->map(fn ($i) => ['id' => $i, 'name' => "アイテム{$i}"]);

$perPage = 15;
$currentPage = request()->integer('page', 1);

$paginator = new LengthAwarePaginator(
    items: $items->forPage($currentPage, $perPage),
    total: $items->count(),
    perPage: $perPage,
    currentPage: $currentPage,
    options: ['path' => request()->url()]
);

よく使うインスタンスメソッド

$paginator = User::paginate(15);

$paginator->currentPage();     // 現在のページ番号
$paginator->lastPage();        // 最後のページ番号(simplePaginate では使用不可)
$paginator->total();           // 総件数(simplePaginate では使用不可)
$paginator->perPage();         // 1ページあたりの件数
$paginator->count();           // 現在ページの件数
$paginator->firstItem();       // 現在ページの最初のアイテムの番号
$paginator->lastItem();        // 現在ページの最後のアイテムの番号
$paginator->hasPages();        // 複数ページが存在するか
$paginator->hasMorePages();    // 次のページが存在するか
$paginator->onFirstPage();     // 最初のページか
$paginator->onLastPage();      // 最後のページか
$paginator->nextPageUrl();     // 次のページURL
$paginator->previousPageUrl(); // 前のページURL
$paginator->url(3);            // ページ3のURL
$paginator->items();           // 現在ページのアイテム配列

まとめ

  • paginate() — 総件数とページ番号リンクが必要な場合(一般的なリスト画面)
  • simplePaginate() — 「前へ」「次へ」リンクのみで十分な場合(高速)
  • cursorPaginate() — 大量データ・無限スクロール・頻繁な書き込みがある場合(最高パフォーマンス)
@foreach ($users as $user)
    <p>{{ $user->name }}</p>
@endforeach

{{ $users->links() }}
paginate() の結果をビューに渡し、links() でページリンクを出力するだけです。 現在のページは page クエリパラメーターから自動で検出されます。
ページネーターをルートから直接返すと自動的にJSONに変換されます。 APIリソースと組み合わせるには UserResource::collection($paginator) を返します。 レスポンスには data(レコード配列)と各種メタ情報が含まれます。
Last modified on March 29, 2026