夏だわっしょいページネーションまつり
Paginationとは、リスト表示なんかした時に「●●件ずつ区切って表示」という処理をやってくれる便利機能です。
findの代わりにDBの情報を持ってきてくれるので、加工済みデータ等には使えません。
Paginationがやってくれる動きは、だいたいこんな感じ。
- データベースからの出力用を分割(SQLのlimitステートメント) (データベース検索条件をfindAllでなく、Paginatorに渡す【検索】)
- CakePHPで自動認識できるページリンクURLを作成する(表示用PaginatorにURL用のデータを渡す【表示】)
**使い方(標準)
1.2以降はコントローラーの機能として存在しているようです。
controller.phpの中をチラ見してみると、paginationの機能がなんとなくわかります。
その昔は、えらい人が作った自作コンポーネントなどでみんな潤っていたそうなので先人の知恵に感謝。
**コントローラー内に書く事。
$helpers = array('Paginator'); function hoge() { //使いたいfunction内でpaginateに指定。 $this->paginate = array( 'conditons' => array(), 'fields' => array(), 'page' => 1, 'limit' => 20, 'sort' => '', 'direction' => 'ASC', 'recursive' => 1 ); //こうして取れた結果をviewに渡す時はset関数で以下のように定義。 $this->set('result', $this->paginate()); }
ソートまでしてデータを出してくれます。あらかじめ初期条件としてページ条件(page)、ソート条件(sort、direction)を与えたいときは
$this->paramsに配列で与えてやれば、最終的に条件をマージしてくれます。
//modelHogeのデータを、idでsortした結果を変数にセット $this->params['sort'] = $id; $this->set('result', $this->paginate('ModelHoge'));
**ビューで書く事
表示はpaginator helperを使います。
★カウンタ(ページ 1/5 1-10 みたいな表示↓)
$paginator->counter(array('format' => 'ページ %page% / %pages% %start%-%end%')));
- 引数
- format
- カウンターのフォーマット
- 定数
- %page%
- 現在のページ
- %pages%
- 総ページ数
- %current%
- 現在表示件数
- %count%
- 全件数
- %start%
- 表示中件数(〜から)
- %end%
- 表示中件数(〜まで)
★前へ(prev)と次へ(next)
$Paginator->prev("<", array(), null, null); $Paginator->next(">", array(), null, null);
- 引数
- $title
- (string)リンク文字。デフォルトはprevだと「<< previous」nextだと「Next >>」
- $options
- (array)リンクのオプション。オプション詳細については後述。
- $disabledTitle
- (string)リンク無効時のタイトル
- $disabledOptions
- (array)無効リンク時のオプション。オプション詳細はやっぱり下。
- 戻り値
prev(next)のリンク、又はリンク無効時のタイトル。
★最初(first)と最後(last)
$Paginator->first("<", array()); $Paginator->last(">", array());
- 引数
- $title
- (string)リンク文字。デフォルトはfirstとかlastとかじゃないですかね。あとで調べます。
- $options
- (array)リンクのオプション。オプション詳細については後述。
★paginationのoptions
- $options['sort']
- ソートキー
- $options['direction']
- ソートの方向(デフォルトはASC)
- $options['format']
- カウンターのフォーマット。range、pages、custom(デフォルトはcustom)
customでは定数を仕様できます。(上記view項目カウンター名の項を参照)
- $options['separator']
- 1 of 20 pages みたいな表示の「of」にあたる部分(デフォルトは「of」)
- $options['url']
- アクションのURL
- $options['model']
- 使用するモデルの名前
- $options['escape']
- リンクのタイトルがエスケープできるか否か(デフォルトは「true」)
- $options['update']
- Ajaxで呼び出された結果のDOM id 未指定なら普通のHTMLリンク使います。
- $options['indicator']
- Ajaxのリクエスト時に参照する(インジケーターの役割)DOM IDの要素
paginationの注意
引数付きのfunctionの中でpaginationを使うとhoge.jp/cont/func1/arg/page:2になってほしくても、hoge.jp/cont/func1/page:2になってしまいます。
funcにも「そんな引数イラネ」と怒られる事もしばしば。じゃあ、どうしろというのか。
cake/libs/router.phpをいじるという男気溢れるやり方以外で思いつくのは
勝手にオプション大作戦
optionでarray('url' => '/controller/action/param1/')と指定するくらいです。
paginatorヘルパー使用時にオプションでurlにパラメーターを渡してしまいましょうという魂胆です。
スマートなやり方教わりましたよ。
$paginator->options = array('url' => $this->passedArgs );
id:e-eg9さんありがとうございます。
Ajaxでおしゃれにページネーション
Ajaxを使うとオシャレにページネイションできます。
参考はココ→http://bakery.cakephp.org/articles/view/advanced-pagination-1-2
★おしゃれページネーションのビューで書く事
まず、layoutで以下のように記述し、ajaxを使っていたらprototype.jsを読み込む設定をします。
link('prototype');
お次に任意のViewです。読み込み中に表示させる「now loading」的な画像を用意しておきます。これは好きなものでかまいません。
ここやここでおしゃれ画像を探すといいでしょう。
image('ajax-loader.gif'); renderElement('cnt/paging');
この時点で、ページングはエレメントの中で行っております。
読み込み用エレメントを作っておけば、いろんなページで使いまわせて経済的ですね。
という訳で、エレメントを作らないといけません
この例では、エレメントはコントローラーと同じ名前のフォルダに入れてます。
ちなみに置き場は「elements/cnt/paging.ctp
//paginatorのオプションは上記参照で。 $paginator->options( array( 'update' => 'CntPaging', 'url' => array( 'controller' => 'Cnt', 'action' => 'display' ), 'indicator' => 'LoadingDiv' ) ); //カウンターを表示させます。 Showing Page counter(); //ソート機能使ってます。 sort('Name', 'name'); sort('Id', 'id'); //次へ、とか、もどる、とか。 prev(戻る); numbers(array('separator'=>' - ')); next('次へ');
★おしゃれページネーションのコントローラーで書く事
Ajaxで呼ばれた時の挙動などを記述。 Ajaxで呼ばれたかどうかの判断は、RequestHandlerというコンポーネントを使います。
こいつがまたイイやつですが後日ご紹介します。
class CntController extends Controller { var $name = 'Cnt'; var $components = array('RequestHandler'); var $paginate = array( 'limit' => 15, 'page' => 1, 'order' => array ( 'name'=>'asc' ) ); function display() { $this->set('datas', $this->paginate('data')); //Ajaxだったら、$this->viewPathを先程作成したエレメントに変更。 if($this->RequestHandler->isAjax()) { $this->viewPath = 'elements'.DS.'Cnt'; $this->render('paging'); } } }
力尽きました。続き(修正)後日。
というかですね。JUGEMじゃなくてwikiを借りようと思っていますよ*1
だって書き辛いんだもの!
*1:結果はてなを借りました