かばだんなさん かく語りぬ Header Image

CakePHPのPaginatorに独自のパラメータを追加

本項はCakePHP1.3で動作するように記述しています。CakePHP2.3をご利用の方はコチラをごらんください。

CakePHP の一覧表示には標準搭載のPaginate機構を使う事が多いと思います。お手軽ですから。bakeで焼いたままで、ソートや改ページといった細かい手間も省いてくれますしね。

でも、一覧画面でありがちな「条件で絞り込み」みたいな要件にどう対応したらいいのかってドンピシャで書いてるところ少ないんですよね。前に確かに実装したのにな・・・って事で覚書。(今回はCakePHP 1.3.10 で動作確認しています。)

【今回の要件】

例えば、人の一覧画面で、[全て|男のみ|女のみ]みたいなスイッチで絞り込みをしたいとしましょう。

やり方は色々あるのですが、どうせなら通常「http://あああ.com/・・・/index/page:2/sort:name/derection:asc」とかなってるURLにさらに「/seibetu:1」みたいな独自のパラメータが追加できればいいですよね。

【namedパラメータが途中で消えないようにしよう(View編)】

この場合は Viewファイルに

<?php
// ページネータが自動生成してくれるリンクに独自のパラメータも追加してもらう
if (isset($this->params['named']['seibetu'])) {
	$paginator->options(array('url' => array('seibetu' => $this->params['named']['seibetu'])));
}

// 絞り込み用のリンク作成
$str = sprintf("[ %s | %s | %s ]",
	$this->Paginator->link('全て', array('seibetu'=>'')),
	$this->Paginator->link('男のみ', array('seibetu'=>'1')),
	$this->Paginator->link('女のみ', array('seibetu'=>'2'))
);
?>

と書きます。これでページが変わろうとソート順が変わろうと、絞り込み条件はパラメータとして引き継がれ続けます。

ちなみに余談ですが、上記ソース中「$paginator」と「$this->Paginator」は同じ物です。HtmlHelperが「$html」でも「$this->Html」でもアクセスできるのと同じです。変数名が短い方がいいか、ヘルパを操作しているのが一目で分かる可読性の高さを好まれるか、お好きな方をどうど。(そりゃ速度性能から言えば$paginatorの方が速いけど、万分の1秒も変わらないだろうから・・・・。)

【引き継がれた条件で絞り込み検索(Controller編)】

次はコントローラ側です。ここではリクエストパラメータを受け取って絞り込み検索を行います。Bakeで焼いただけの自動生成されたソースでは

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

となっていると思います。これを

	$conditions = array();
	if(isset($this->params['named']['seibetu'])) {
		$seibetu = $this->params['named']['seibetu'];
		$conditions = array(
			'Person' => array('seibetu' => $seibetu)
		);
	}
	$this->set('persons', $this->paginate(null, $conditions));

といった感じで書き換えればOKです。

【POSTで条件を送る場合(余談)】

単独ならこれでもいいのですが、複数の条件を入力して1回でドカン!と再検索しようとするとどうしてもフォームを作ってPOSTで送る感じになりますよね。
これこそ実装方式は色々ありますが、かばだんなさんは上記コントローラ編のソースの前に下記のように書いています。

	if ($_SERVER['REQUEST_METHOD']=='POST' && isset($this->params['data'][$this->modelNames[0]]['seibetu'])) {
		// ポストされたデータを名前付き変数に再セット
		$this->params['named']['seibetu'] 
			= $this->params['data'][$this->modelNames[0]]['seibetu'];
		// で、そのまま自分にリダイレクト
		$this->redirect($this->params['named']);
	}

リダイレクトは不要と思われるかもしれませんね。はい、なくても動きます。
単に かばだんなさん の趣味ですw

しかしまぁ、「実装としては何てことはないけど忘れてしまうと大変」というのが、規約系フレームワークの辛い所ですね(苦笑。

One Comment

  1. […] http://blog.kabadna.com/20110731-1297/ CakePHPのPaginatorに独自のパラメータを追加する方法がのっている。 […]


コメントを残す