【CakePHP入門】Pagenation(ページネーション)の使い方

こんにちは!フリーエンジニアのせきです。

CakePHPには、簡単にページネーションを実装してくれる機能があります。

この記事では、

・ページネーションとは何か知りたい
・CakePHPページネーション機能の使い方を知りたい

という基本的な内容から、

・テーブルを結合してページネーションする方法を知りたい

といった応用的な内容に関しても解説していきます。

今回はそんなCakePHPのページネーションの使い方について、わかりやすく解説します!

目次

Pagenation(ページネーション)とは

ページネーションとは、情報の多いページを複数のページに分割し、各ページへのリンクを表示することで、情報にアクセスしやすくする機能です。

Webシステムでは、データベースから取得した情報を一覧表示する時によく使われます。

ページネーションを使うことで、ユーザにとって情報を探しやすく、使いやすいシステムになります。

CakePHPではControllerクラスに設定を行うことで、簡単にページネーションの機能を使うことができます。

これから、具体的なページネーションの使い方について解説してきます。

ページネーションの使い方

事前準備

ページネーションの機能を確認するため、ユーザ情報の一覧を表示する機能を作成します。

使用するのは、以下のUSERテーブルです。

CREATE TABLE USER
(
	ID INT NOT NULL AUTO_INCREMENT,
	NAME VARCHAR(32),
	ADDRESS VARCHAR(32),
	AGE INT,
	COMPANY_ID INT,
	PRIMARY KEY (ID)
);

Model、Controller、Viewの実装は、以下のようにしています。

・Model
[プロジェクトのパス]/src/Model/Table/UserTable.php

<?php
namespace App\Model\Table;

use Cake\ORM\Table;

class UserTable extends Table
{
	public function initialize(array $config)
	{
	}
}

[プロジェクトのパス]/src/Model/Entity/User.php

<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class User extends Entity
{
}

・Controller

USERテーブルを全件検索します。
[プロジェクトのパス]/src/Controller/UserController.php

<?php
namespace App\Controller;

use App\Controller\AppController;

class UserController extends AppController
{
	public function index()
	{
		$this->set('user', $this->User->find('all'));
	}
}

・View

USERテーブルのすべての情報を表示します。
[プロジェクトのパス]/src/Template/User/index.ctp

<table>
    <tr>
        <th>ID</th>
        <th>NAME</th>
        <th>ADDRESS</th>
        <th>AGE</th>
        <th>COMPANY_ID</th>
    </tr>
    <?php foreach ($user as $user): ?>
    <tr>
        <td><?= $this->Number->format($user->ID) ?></td>
        <td><?= h($user->NAME) ?></td>
        <td><?= h($user->ADDRESS) ?></td>
        <td><?= $this->Number->format($user->AGE) ?></td>
        <td><?= $this->Number->format($user->COMPANY_ID) ?></td>
    </tr>
    <?php endforeach; ?>
</table>

「http://[サーバ名]/[プロジェクト名]/user」にアクセスすると、以下のような画面が表示されます。
001
あらかじめ8件のデータをテーブルに挿入してあります。

基本的な使い方

ページネーション機能を使うには、Controllerクラスの$paginate変数にページネーションの設定を追加します。

1ページに表示するデータの件数limitプロパティを使用して設定します。

3件ずつ表示する場合は、以下のように設定します。

public $paginate = [
	'limit' => 3
];

paginateメソッドを使用し、Modelに渡すデータを作成します。

$this->set('user', $this->paginate());

UserControllerクラスは、以下のようになります。

<?php
namespace App\Controller;

use App\Controller\AppController;

class UserController extends AppController
{
	public $paginate = [
		'limit' => 3 // 1ページに表示するデータ件数
	];

	public function index()
	{
		$this->set('user', $this->paginate());
	}
}

次に、ページネーションのためのリンクをViewに追加します。

Viewの中では、PaginatorHelperクラスという各ページへのリンクやページ番号の制御を行うクラスを使用します。

「$this->Paginator」で使用することができ、以下のような機能が用意されています。

<?= $this->Paginator->first('<<') ?>
<?= $this->Paginator->prev('<') ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next('>') ?>
<?= $this->Paginator->last('>>') ?>

$this->Paginator->first(‘<<‘)」は、先頭ページへのリンクを返します。リンク文字「'<<‘」は任意に指定できます。

$this->Paginator->prev(‘<‘)」は、前ページへのリンクを返します。リンク文字「'<‘」は任意に指定できます。

$this->Paginator->numbers()」は、ページ番号で各ページへのリンクを返します。

$this->Paginator->next(‘>’)」は、次ページへのリンクを返します。リンク文字「’>’」は任意に指定できます。

$this->Paginator->last(‘>>’)」は、最終ページへのリンクを返します。リンク文字「’>>’」は任意に指定できます。

これらを使用し、index.ctpを以下のように修正します。

<table>
    <tr>
        <th>ID</th>
        <th>NAME</th>
        <th>ADDRESS</th>
        <th>AGE</th>
        <th>COMPANY_ID</th>
    </tr>
    <?php foreach ($user as $user): ?>
    <tr>
        <td><?= $this->Number->format($user->ID) ?></td>
        <td><?= h($user->NAME) ?></td>
        <td><?= h($user->ADDRESS) ?></td>
        <td><?= $this->Number->format($user->AGE) ?></td>
        <td><?= h($user->company->NAME) ?></td>
    </tr>
    <?php endforeach; ?>
</table>
<div class="paginator">
    <ul class="pagination">
        <?= $this->Paginator->first('<<') ?>
        <?= $this->Paginator->prev('<') ?>
        <?= $this->Paginator->numbers() ?>
        <?= $this->Paginator->next('>') ?>
        <?= $this->Paginator->last('>>') ?>
    </ul>
</div>

もう一度「http://[サーバ名]/[プロジェクト名]/user」にアクセスすると、3件ずつページングされています。

1ページ目
002

2ページ目
003

ソートの使い方(order)

CakePHPのページネーション機能には、データのソート機能も含まれています。

表示するデータをソートする場合は、Controllerクラスで$paginate変数のorderプロパティを使用します。

public $paginate = [
	'limit' => 10, // 1ページに表示するデータ件数
	'order' => [
		'User.AGE' => 'asc' // AGEの昇順でソート
	]
];

上のように設定して表示すると、AGEの昇順でソートされています。

(ソートされた結果がわかりやすいように、1ページに表示するデータ件数は「10」に変更しています)
004

ソートは複数条件で行うこともできます。

public $paginate = [
	'limit' => 10, // 1ページに表示するデータ件数
	'order' => [
		'User.ADDRESS' => 'asc', // ADDRESSの昇順でソート
		'User.AGE' => 'asc' // AGEの昇順でソート
	]
];

上のように設定すると、ADDRESSの昇順でソートし、さらにそのデータをAGEの昇順でソートします。
005

ソートの使い方(sort)

$paginate変数のorderプロパティによるソートは、一覧表示時に既にソートされていますが、ユーザが一覧のヘッダをクリックして、ソートを行う機能もあります。

index.ctpの一覧ヘッダ部分を、以下のように修正します。

<tr>
    <th><?= $this->Paginator->sort('ID', 'ID') ?></th>
    <th><?= $this->Paginator->sort('NAME', 'NAME') ?></th>
    <th><?= $this->Paginator->sort('ADDRESS', 'ADDRESS') ?></th>
    <th><?= $this->Paginator->sort('AGE', 'AGE') ?></th>
    <th><?= $this->Paginator->sort('COMPANY_ID', 'COMPANY_ID') ?></th>
</tr>

ヘッダ文字列がリンクになり、クリックするとその項目でソートされます。

下は「NAME」をクリックしてソートした状態です。
006

テーブルを結合してページネーションする方法

ページネーション機能を使用して、複数のテーブルを結合して一覧表示し、ページングすることができます。

一覧に表示されているCOMPANY_IDを、COMPANYテーブルに登録されている名前で表示してみます。

USERテーブルが持つCOMPANY_IDに紐づく、COMPANYテーブルを作成します。

CREATE TABLE COMPANY
(
	ID INT NOT NULL AUTO_INCREMENT,
	NAME VARCHAR(32),
	PRIMARY KEY (ID)
);

以下のデータを挿入します。

insert into COMPANY values(1, 'A Company');
insert into COMPANY values(2, 'B Company');
insert into COMPANY values(3, 'C Company');
insert into COMPANY values(4, 'D Company');

COMPANYテーブルのModelを作成します。

[プロジェクトのパス]/src/Model/Table/CompanyTable.php

<?php
namespace App\Model\Table;

use Cake\ORM\Table;

class CompanyTable extends Table
{
}

[プロジェクトのパス]/src/Model/Entity/Company.php

<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class Company extends Entity
{
}

USREテーブルのModelに関連の定義を追加します。

[プロジェクトのパス]/src/Model/Table/UserTable.php

<?php
namespace App\Model\Table;

use Cake\ORM\Table;

class UserTable extends Table
{
	public function initialize(array $config)
	{
		$this->belongsTo('Company');
	}
}

Controllerクラスで$paginate変数のcontainプロパティを使用し、以下のように設定します。

public $paginate = [
	'limit' => 3, // 1ページに表示するデータ件数
	'order' => [
		'User.ID' => 'asc' // IDの昇順でソート
	],
	'contain' => ['Company'] // Companyテーブルを結合する
];

index.ctpを以下のように修正します。

<table>
    <tr>
        <th>ID</th>
        <th>NAME</th>
        <th>ADDRESS</th>
        <th>AGE</th>
        <th>COMPANY_NAME</th>
    </tr>
    <?php foreach ($user as $user): ?>
    <tr>
        <td><?= $this->Number->format($user->ID) ?></td>
        <td><?= h($user->NAME) ?></td>
        <td><?= h($user->ADDRESS) ?></td>
        <td><?= $this->Number->format($user->AGE) ?></td>
        <td><?= h($user->company->NAME) ?></td>
    </tr>
    <?php endforeach; ?>
</table>
<div class="paginator">
    <ul class="pagination">
        <?= $this->Paginator->first('<<') ?>
        <?= $this->Paginator->prev('<') ?>
        <?= $this->Paginator->numbers() ?>
        <?= $this->Paginator->next('>') ?>
        <?= $this->Paginator->last('>>') ?>
    </ul>
</div>

COMPANYテーブルのNAMEは、「$user->company->NAME」で取得できます。

表示するとCOMPANYテーブルが結合され、ページングも実装されています。
007

まとめ

今回はページネーションの使い方について解説しました。

CakePHPのページネーション機能を使うと、ページングやソートを簡単に実装することができますので、ぜひ使ってみてください。

ページネーションの使い方を忘れてしまったら、この記事を思い出して下さい!

この記事を書いた人

フリーランスでWebシステム開発やゲーム開発をしています。
読者の方にプログラミングの面白さをお伝えしたいです。

目次