- 更新日: 2015年10月30日
- PHP & CakePHP
CakePHP3でモデルを使わないページネーション
CakePHP3 のプロジェクトで、モデル(DBテーブル)を使わないデータのコレクションをページングさせて表示させたい機会がありました。GitHub で見つけた jasongrimes/php-paginator を使って解決しました。感謝!
https://github.com/jasongrimes/php-paginator
— 環境 —
CakePHP 3.1.1
PHP 5.5.19
jasongrimes/paginator 1.0.2
デフォルトの PaginatorComponent ソースを読んでみた
まずは、CakePHP3にデフォルトでバンドルされている PaginatorComponent を使って実現できないか調べました。ソースを読んでみたところ、デフォルトの PaginatorComponent でのページネーションは、モデルを使うことを前提としているっぽい…。深追いしてないんであまり自信ないですけど。
vendor/cakephp/cakephp/src/Controller/Component/PaginatorComponent.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
namespace Cake\Controller\Component; // ... class PaginatorComponent extends Component // ... public function paginate($object, array $settings = []) { // ... $results = $query->all(); $numResults = count($results); $count = $numResults ? $query->count() : 0; // ... |
Controller::paginate() の実装で、$query->all() または $query->count() を使ってページングに必要なデータの総件数を取得してあります。独自コンポーネントを作って、paginate() メソッドをモデルを使わずに動くようにオーバーライドする方法でも良いかもしれませんけど、面倒なのでやめました。
ページネーション — CakePHP Cookbook 3.x ドキュメント
デフォルトの PaginatorComponent を使って、モデルなしのデータ集合のページングを実現できる方法があれば、ぜひご教授下さい。
jasongrimes/paginator でページネーション実装
代わりに GitHub で探したところ、良さ気な Paginator ライブラリを発見してこれで一発解決しました。
https://github.com/jasongrimes/php-paginator
Twitter Bootstrap にも対応してて綺麗に表示されます。README 通りに進めればOKです。
まずは、Composer でインストール。
1 2 3 |
$ composer require "jasongrimes/paginator:~1.0" |
CakePHP アプリケーションのコントローラーにページング実装。
src/Controller/ItemsController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
namespace App\Controller; use App\Controller\AppController; use JasonGrimes\Paginator; class ItemsController extends AppController { public function index($page_num = '1') { // ... $totalItems = 1000; $itemsPerPage = 50; $currentPage = $page_num; $urlPattern = '/foo/page/(:num)'; $paginator = new Paginator($totalItems, $itemsPerPage, $currentPage, $urlPattern); $this->set('paginator', $paginator); } // ... } |
README を参考に書いてますけど、実際には $totalItems, $currentPage などの値はデータ集合やパラメータなどから動的に取得します。
ページング用の $currentPage の値は URL パスのパラメータから取得するので、ルーティング設定が必要。以下のような感じです。
config/routes.php
1 2 3 4 5 6 7 8 |
Router::scope('/items', ['controller' => 'Items'], function ($routes) { $routes->connect( '/foo/page/:num', ['action' => 'index'], ['num' => '[0-9]+', 'pass' => ['page']] ); } ); |
最後に、ビューで $paginator を出力。
src/Template/items/index.ctp
1 2 |
// ... <?= $paginator; ?> |
以上で終了。CakePHP でモデルを使わないデータ集合の pagination を実装できました。
- PHP & CakePHP の関連記事
- PHP+MySQLでNo such file or directoryエラー
- bin/cakeコマンドでintlエラーが出る場合の対処(CakePHP)
- CakePHPアプリケーションをCapistranoでデプロイ
- Integrity constraint violation:Column ‘created’ in order clause is ambiguousエラー/CakePHP
- CakePHPでDB関連テーブルのレコード・データを取得
- CakePHPでカラム属性に別名/エイリアスを付ける仮想フィールド
- CakePHPで日付選択フォームのカスタマイズ
- CakePHP3で現在のコントローラー名・アクション名を取得
- PHPインストールでconfigure: error: freetype.h not foundエラー
- CakePHPでログイン後に元のページにリダイレクトさせる
Leave Your Message!