CakePHP3で検索結果をページネーション

シェアする

1ページあたりに表示されるレコードの件数を制御したいという状況はよくあると思います。
今回はページネーションを使用して、取得したレコードをページ分けするやり方を紹介したいと思います。

シンプルに1ページあたりの件数と、表示順の設定だけをしていきます。

スポンサーリンク

データの準備

以下のテーブルを用意して、適当にデータを入れてきます。


CREATE TABLE `articles` (
  `id` int(11) NOT NULL,
  `title` varchar(50) NOT NULL,
  `body` text,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  `delete_flg` int(11) NOT NULL DEFAULT '0' COMMENT '0:未削除,1:削除'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ページネーションの検索条件定義

ページネーションを使用したいコントローラーで、以下のコードを記述します。
【ArticlesController.php】


class ArticlesController extends AppController
{
    public $paginate = [
        'limit' => 5,
        'order' => [
            'Articles.created' => 'desc'
        ]
    ];

    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('Paginator');
    }
}

「$paginate」に「limit」と「order」をセットしています。
「limit」が1ページあたりの件数、
「order」がどのカラムでソートするか
を定義しています。

上記の場合、
1ページあたりの件数を「5件」、
「Articlesテーブルのcreatedカラム」の「降順」でソートする
というような感じです。

「order」の書式は、キーを「ソート対象のカラム」にし、バリューを「asc」もしくは「desc」の配列構造にする必要があります。

また、initialize()にて「Paginator」のコンポーネントを読み込む必要があります。

一覧データの取得

モデルのfindメソッドを使って一覧のデータを取得します。
ここではArticlesテーブルのレコードのうち、削除フラグが「0」の記事を取得してみます。
【ArticlesController.php】


    public function index()
    {
        $articles = $this->Articles->find('all')
            ->where(['delete_flg' => '0']);

        $this->set(compact('articles'));
    }

一覧データの表示

view側で取得したデータの一覧をテーブルで表示します。
【Template/Articles/index.ctp】


<div>
    <table>
        <tr>
            <th>ID</th>
            <th>タイトル</th>
            <th>作成日</th>
        </tr>
        <tbody>
        <?php foreach ($articles as $article) { ?>
            <tr>
                <td><?php echo $article['id']; ?></td>
                <td><?php echo $article['title']; ?></td>
                <td><?php echo $article['created']->format('Y/m/d'); ?></td>
            </tr>
        <?php } ?>
        </tbody>
    </table>
</div>

もし、ページネーションを使わないままview変数を使用して記事一覧を表示させると、以下のように全ての記事一覧が1ページに表示されてしまいます。

そこで、データ取得後に1行追加し、以下のようにします。


    public function index()
    {
        $this->loadModel('Articles');
        $articles = $this->find('all')
            ->where(['delete_flg' => '0']);

        $arcicles = $this->paginate($articles);  //←この行を追加

        $this->set(compact('articles'));
    }

上記により、ページ分けされた検索結果が「$articles」に代入されます。

ページリンクの表示

ビューのテンプレートファイルで、ページリンクを表示したい部分に以下のコードを差し込みます。今回は</table>の後に入れました。


<div>
    <ul class="pagination">
        <li>
            <?php 
                if ($this->Paginator->hasPrev()) {  
                    echo $this->Paginator->prev('< 前へ');
                }
            ?>
        </li>
            <?php echo $this->Paginator->numbers(); ?>
        <li>
            <?php
                if ($this->Paginator->hasNext()) {  
                  echo $this->Paginator->next('次へ >');
                }
            ?>
        </li>
    </ul>
</div>

PaginationHelperクラスの関数を使用しています。
「$this->Paginate->hasPrev()」は現在のページが先頭でない場合に「true」を返します。
「$this->Paginate->hasNext()」は現在のページが最終でない場合に「true」を返します。
「$this->Paginate->prev()」は前のページへのリンクを生成します。
「$this->Paginate->next()」は次のページへのリンクを生成します。
「$this->Paginate->numbers()」はページ番号ごとにリンクを生成します。

上記のコードとcssを組み合わせるとこんな感じになります。
ulタグで使用しているクラス「pagination」はデフォルトでcssに入っているのでコピペしても使用できます。
↓現在先頭の1ページ目にいます

↓2ページ目に移動しました

if文を使って、先頭ページなら「前へ」リンクを非表示にしています。

今回は使用していませんが、以下のようなものも使えます。
「$this->Paginate->first()」は先頭ページへのリンクを生成します。
「$this->Paginate->last()」は最終ページへのリンクを生成します。

こちらのドキュメントを読み込むことで、他にも細かい制御が可能です。

PaginatorHelperは、ページ番号や次/前のリンクなどの改ページコントロールを出力するために使用されます。

サンプルプログラム

こちらに今回作成したサンプルがございます。

Contribute to ChatLune/blog-CakePHP-pagination development by creating an account on GitHub.

テスト用に作成したテーブルのダンプファイルと、controllerとviewファイルです。

飲食業界からIT業界に転身してきて現在2年目です。PHPの経験がメインとなります。これまで自分がPHPを扱ってきた上で、モヤモヤしてきたことをメインに記事にしていきますのでよろしくお願いいたします。

スポンサーリンク

シェアする

フォローする