よくある検索画面でPaginationを使う

2008/12/25追記
ソースコードの中にコメントとプログラムを追記しました。これがないとXSSが発生する可能性があるのでご注意下さい。


cakePHP1.2 RC3を利用してます。

よくデータの管理画面なんかで、簡易検索機能として検索条件を入れて、その結果を一覧表示するのってありますよね。
Googleの検索画面なんかもそう。
この場合、検索条件を最初にPOSTして、その後、検索結果一覧画面が表示されます。結果一覧では検索条件を変えたりするために、検索入力エリアがあり、そこにPOSTした検索条件が保持されています。

これをCakeで作る場合、検索結果一覧はPagination機能を使ってお手軽にページングしたい、でも検索条件もフォームエリアに保持し続けたい、それらを1画面で表現したい、そんな時にどうするか。



まず、最初の検索条件をPOSTすると、$this->dataにデータが入ります。その後、Paginationでページングして2ページ目とかソートとかのリンクを遷移すると、POSTではなくURLの中にパラメータを入れるGETリクエストになり、データは$this->passedArgsに入ります。(POSTしたデータをページングで引き回す方法はここを参照: http://d.hatena.ne.jp/cakephper/20080907/1220796088 )

そこで、POST時は$this->dataから値を取得、Get時は$this->passwdArgsから値を取得します。Getの際に検索条件の指定も何も無い初回のGETなのか、PaginationのURLからの遷移なのかを判断します。これはcount($this->passedArgs)を使って配列の数を数えて1以上であればPaginationのURLからの遷移と判断します。
PaginationのURLからの遷移の場合は、フォームに検索条件の値を保持させるために、$this->dataに$this->passedArgsの値をセットします。


コントローラでは下記のようにします。

if( !empty($this->data) ){

	$search = $this->data[$this->name];

}elseif( count($this->passedArgs) ){

	$search = $this->passedArgs;

	$this->data[$this->name] = $search;

}

/* 2008/12/25追記
   $search配列は、不要なキーと値の組み合わせが入る可能性があるので
  必要なキーのみに絞り、値をurlencodeする処理が必要です。
  そうしないと、XSSが発生する可能性があります。
*/
   $search_list = array( 'key1', 'key2','key3' );

   $search_value = array();
   foreach( $search_list as $value ){
        $search_value[ $value ] = urlencode( $search[$value] );
    
   }



$this->set( 'searchword' , $search_value );


Viewでは下記のようにしてPaginationのURLを生成します。

<?php $paginator->options(array('url' =>  $searchword  )); ?>