ページネーション

CodeIgniterは、シンプルながらも柔軟なページネーションライブラリを提供します。テーマ設定が容易で、モデルと連携し、単一ページで複数のページネーターをサポートできます。

ライブラリの読み込み

CodeIgniterの他のサービスと同様に、Config\Services を介して読み込むことができますが、通常は手動で読み込む必要はありません。

<?php

$pager = \Config\Services::pager();

モデルを使用したページネーション

ほとんどの場合、データベースから取得した結果をページネーションするために、Pagerライブラリを使用します。Modelクラスを使用する場合、組み込みのpaginate()メソッドを使用して、現在のバッチの結果を自動的に取得し、Pagerライブラリを設定してコントローラーで使用できるようにすることができます。page=Xクエリ変数を使用して、現在のURLから表示する必要がある現在のページを読み取ります。

アプリケーションにユーザーのページネーションされたリストを提供するには、コントローラーのメソッドは次のようになります。

<?php

namespace App\Controllers;

class UserController extends BaseController
{
    public function index()
    {
        $model = new \App\Models\UserModel();

        $data = [
            'users' => $model->paginate(10),
            'pager' => $model->pager,
        ];

        return view('users/index', $data);
    }
}

この例では、最初にUserModelの新しいインスタンスを作成します。次に、ビューに送信するデータを準備します。最初の要素はデータベースからの結果、**users**で、正しいページのデータが取得され、ページごとに10人のユーザーが返されます。ビューに送信する必要がある2番目のアイテムは、Pagerインスタンス自体です。便宜上、Modelは使用したインスタンスを保持し、公開プロパティ$pagerに格納します。そのため、それを取得してビューの$pager変数に代入します。

ページネーションのクエリのカスタマイズ

モデルでページネーションのクエリをカスタマイズするには、paginate()メソッドの前にQuery Builderメソッドを追加できます。

WHERE句の追加

WHERE条件を追加する場合は、条件を直接指定できます。

// In your Controller.
$model = new \App\Models\UserModel();

$data = [
    'users' => $model->where('ban', 1)->paginate(10),
    'pager' => $model->pager,
];

条件を別のメソッドに移動することもできます。

<?php

namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model
{
    // ...

    public function banned()
    {
        $this->builder()->where('ban', 1);

        return $this; // This will allow the call chain to be used.
    }
}
// In your Controller.
$model = new \App\Models\UserModel();

$data = [
    'users' => $model->banned()->paginate(10),
    'pager' => $model->pager,
];

JOIN句の追加

別のテーブルを結合できます。

<?php

namespace App\Models;

use CodeIgniter\Model;

class NewsModel extends Model
{
    protected $table = 'news';

    // ...

    public function getPagination(?int $perPage = null): array
    {
        $this->builder()
            ->select('news.*, category.name')
            ->join('category', 'news.category_id = category.id');

        return [
            'news'  => $this->paginate($perPage),
            'pager' => $this->pager,
        ];
    }
}

重要

Model::paginate()メソッドは、**Model**と**Model**内の**Query Builder**インスタンスを使用します。したがって、$db->query()と共にModel::paginate()を使用しようとすると、$db->query()はクエリをすぐに実行し、Query Builderに関連付けられていないため、**機能しません**。

Query Builderで記述できない複雑なSQLクエリが必要な場合は、$db->query()手動ページネーションを使用してみてください。

複数の結果のページネーション

2つの異なる結果セットからリンクを提供する必要がある場合は、データを分離するために、ほとんどのページネーションメソッドにグループ名を渡すことができます。

<?php

namespace App\Controllers;

class UserController extends BaseController
{
    public function index()
    {
        $userModel = new \App\Models\UserModel();
        $pageModel = new \App\Models\PageModel();

        $data = [
            'users' => $userModel->paginate(10, 'group1'),
            'pages' => $pageModel->paginate(15, 'group2'),
            'pager' => $userModel->pager,
        ];

        echo view('users/index', $data);
    }
}
?>

<!-- In your view file: -->
<?= $pager->links('group1') ?>
<?= $pager->simpleLinks('group2') ?>

ページの手動設定

返す結果のページを指定する必要がある場合は、3番目の引数としてページを指定できます。これは、表示するページを制御するデフォルトの$_GET変数とは異なる方法がある場合に便利です。

<?php

$userModel = new \App\Models\UserModel();
$page      = 3;

$users = $userModel->paginate(10, 'group1', $page);

ページのURIセグメントの指定

ページクエリパラメータの代わりに、ページ番号にURIセグメントを使用することもできます。使用するセグメント番号を4番目の引数として指定するだけです。ページャーによって生成されるURIは、**https://domain.tld/foo/bar?page=[pageNumber]**ではなく、**https://domain.tld/foo/bar/[pageNumber]**のようになります。

<?php

$users = $userModel->paginate(10, 'group1', null, $segment);

注:$segmentの値は、URIセグメントの数プラス1より大きくすることはできません。

手動ページネーション

既知のデータに基づいてページネーションを作成する必要がある場合があります。makeLinks()メソッドを使用して手動でリンクを作成できます。このメソッドは、現在のページ、1ページあたりの結果数、アイテムの総数をそれぞれ最初の、2番目の、3番目のパラメータとして取得します。

<?php

namespace App\Controllers;

class UserController extends BaseController
{
    public function index()
    {
        // ...

        $pager = service('pager');

        $page    = (int) ($this->request->getGet('page') ?? 1);
        $perPage = 20;
        $total   = 200;

        // Call makeLinks() to make pagination links.
        $pager_links = $pager->makeLinks($page, $perPage, $total);

        $data = [
            // ...
            'pager_links' => $pager_links,
        ];

        return view('users/index', $data);
    }
}
?>

<!-- In your view file: -->
<?= $pager_links ?>

これはデフォルトでリンクを通常の方法(一連のリンクとして)で表示しますが、4番目のパラメータとしてテンプレートの名前を渡すことで、使用される表示テンプレートを変更できます。詳細については、次のセクションを参照してください。

$pager->makeLinks($page, $perPage, $total, 'template_name');

前のセクションで説明したように、ページクエリパラメータの代わりに、ページ番号にURIセグメントを使用することもできます。makeLinks()の5番目のパラメータとして使用するセグメント番号を指定します。

$pager->makeLinks($page, $perPage, $total, 'template_name', $segment);

注:$segmentの値は、URIセグメントの数プラス1より大きくすることはできません。

1ページに多くのページャーを表示する必要がある場合は、グループを定義する追加のパラメータが役立ちます。

<?php

$pager = service('pager');
$pager->setPath('path/for/my-group', 'my-group'); // Additionally you could define path for every group.
$pager->makeLinks($page, $perPage, $total, 'template_name', $segment, 'my-group');

ページネーションライブラリは、デフォルトでHTTPクエリに**page**クエリパラメータを使用します(グループ名がない場合、またはdefaultグループ名が指定されていない場合)。カスタムグループ名についてはpage_[groupName]を使用します。

期待されるクエリのみを使用したページネーション

デフォルトでは、すべてのGETクエリがページネーションリンクに表示されます。

たとえば、URL **https://domain.tld?search=foo&order=asc&hello=i+am+here&page=2**にアクセスする場合、ページ3のリンクは、他のリンクと共に次のように生成できます。

<?php

echo $pager->links();
// Page 3 link: https://domain.tld?search=foo&order=asc&hello=i+am+here&page=3

only() メソッドを使用すると、既に想定されているクエリにのみ制限することができます。

<?php

echo $pager->only(['search', 'order'])->links();
// Page 3 link: https://domain.tld?search=foo&order=asc&page=3

page クエリはデフォルトで有効になっています。そして、only() はすべてのページネーションリンクで機能します。