こんにちは!フリーエンジニアのせきです。
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」にアクセスすると、以下のような画面が表示されます。
あらかじめ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ページ目
2ページ目
ソートの使い方(order)
CakePHPのページネーション機能には、データのソート機能も含まれています。
表示するデータをソートする場合は、Controllerクラスで$paginate変数のorderプロパティを使用します。
public $paginate = [ 'limit' => 10, // 1ページに表示するデータ件数 'order' => [ 'User.AGE' => 'asc' // AGEの昇順でソート ] ];
上のように設定して表示すると、AGEの昇順でソートされています。
(ソートされた結果がわかりやすいように、1ページに表示するデータ件数は「10」に変更しています)
ソートは複数条件で行うこともできます。
public $paginate = [ 'limit' => 10, // 1ページに表示するデータ件数 'order' => [ 'User.ADDRESS' => 'asc', // ADDRESSの昇順でソート 'User.AGE' => 'asc' // AGEの昇順でソート ] ];
上のように設定すると、ADDRESSの昇順でソートし、さらにそのデータをAGEの昇順でソートします。
ソートの使い方(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」をクリックしてソートした状態です。
テーブルを結合してページネーションする方法
ページネーション機能を使用して、複数のテーブルを結合して一覧表示し、ページングすることができます。
一覧に表示されている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テーブルが結合され、ページングも実装されています。
まとめ
今回はページネーションの使い方について解説しました。
CakePHPのページネーション機能を使うと、ページングやソートを簡単に実装することができますので、ぜひ使ってみてください。
ページネーションの使い方を忘れてしまったら、この記事を思い出して下さい!