ようこそゲストさん

CPA-LABテクニカル

Paginatorの使い方。CakePHP1.2

Paginatorは設定項目が多くてたいへんなので覚書として書いておいた。ページングがとても簡単に扱えるのはたいへん助かる。
なお、こちらも詳しい(CakePHP:ページングを試す)のだけれど、せっかくソースも読んでみたので覚書。
バージョン:CakePHP1.2beta
こちらも参考:PagenatorでPaginateしてみた。

Paginatorとは

データベースからたくさんのデータを引っ張ってきた時、一度に画面に出すと大変なので、自動的にページ分割をしてくれる機能。
prev<< 1 | 2 | 3 | 4 | 5 >>next
というやつ。

あくまでもデータベースから直接引き出せる情報についてのみ

例えばいったんデータベスから大量に引き出して加工してしまった配列そのものをページングしようとしてもできない。なぜならば、Paginatorは
  1. データベースからの出力用を分割し(SQLのlimitステートメント)
  2. CakePHPで自動認識できるページリンクURLを作成する
という検索と表示の2つの機能からできているから。

だから、
1の機能のために、データベース検索条件をfindAllでなく、Paginatorに渡す(検索)
2の機能のために。表示用PaginatorにURL用のデータを渡す(表示)
という2つの作業が必要になる。これが結構似ているものだから、最初はとまどった。この区別をつけておかないとあとで混乱する。
基本的に、1の検索機能は、controller.phpのfunction paginatorの役割であり、2の表示部分は、paginatorヘルパーのfunction群の役割である。

表示リンク形式

http://example.com/cake/~/page:3/sort:value/derection:asc/limit:10
という形で、page,sort,derection,limitが計算される。

1. 検索機能へのパラメータ渡しと実行方法

自分(this)のpaginateメンバ変数に、パラメータを多重配列でセットする。


簡単に言えば
findAllに渡す代わりに、paginatorに渡す
というだけ。findAllよりもたくさんのパラメータを渡すことができるが、既存のfindAllをpaginatorに置き換えるだけで、十分に動く。


書式
$this->paginate=array(
    'conditions' => array(検索条件),
    'fields' => array(取得するカラム),
    'page' => int(数値,最初に表示するページ。デフォルトは1,'last'(小文字)も可*1),
    'limit' => int(数値:showでも可。デフォルトは20),
    'sort' => string(ソートkey:order*2 でもよい。重なった場合はsortが優先される。),
    'direction' => string(asc or desc:デフォルトはasc)
    'recursive' => findAllに与える。
 );
どのパラメータも必須ではない。設定されない場合はデフォルト値または全文検索となる。
tips
カレントのモデル以外の検索条件の設定であれば、上記のパラメータを
$this->paginate=array('モデル名',array(上記の多重配列))
としてやれば設定できる。(uses設定は必要)


上記のように$this->paginateに設定したら、
$this->paginator();
とPaginatorを呼び出すと、その返り値が、表示用の配列*3となる。したがって、
$this->set('example',$this->paginator());
として、viewに情報を渡してあげるのがよいでしょう。

追加的なパラメータの渡し方

なお、$this->paginator();には、さらにパラメータを設定できる。
$this->paginator(
    object(自分以外のモデルを指定できる*4*5省略可)。*6
    scope(検索条件を配列で与える)*7,
    whitelist*8
 );
以下のようなして方法が可能である。
$this->paginator( array('id' => '5') ) ※検索条件のみを配列で与える。
$this->paginator(  array('id' => '5'),whitelist ) ※検索条件とwhitelist
$this->paginator( 'モデル名', array('id' => '5') ) ※モデル名も加えることができる
$this->paginator( 'モデル名', array('id' => '5'),whitelist ) 
$this->paginateでoptionを設定し、さらにメンバ関数呼び出しの時に$this->paginator(array(検索条件))とした場合は、最後の条件で上書きされる。

ソート時の留意点

$this->paginate=array(検索条件)と
$this->paginator(array(検索条件))の違いは

パラメータのデフォルトとして認識されるかどうかである。$this->paginate=array(検索条件)で登録するとデフォルトとなる。

このことは特にソート条件に大きな影響を及ぼす。後から、柔軟にソート条件を変えたい場合は、デフォルト登録せず、関数の引数にしたほうが無難だろう。*9

どのような結果が返ってくるか。


最終的には、
findAll($conditions, $fields, $order, $limit, $page, $recursive);

の結果を返してくれる。
Hack!
ちなみに、そのモデルでfunction paginateを定義しておくと、そちらで処理される(引数は同じ)。そのモデルだけで使うパラメータ、もしくは絶対に使ってはいけないパラメータをここでハックする、ということができるようになっているのでしょう。

remember
表示用のPaginatorヘルパーは、$this->paginateを実行すれば自動的に呼び込まれるので、明示的に呼んでおく必要はない。(もちろん、呼んでおいて構わない)。

実行後に参照可能なパラメータ


この処理後、以下のパラメータをセットしてくれている。
$this->paramas['paging'][モデル名]=array(
  'page'		=> あなたが指定したページ,
  'current'	=> 現在のページ,
  'count'		=> 全レコード数,
  'prevPage'	=> 前ページがあればtrue,なければfalse,
  'nextPage'	=> 次のページがあればtrue、なければfalse,
  'pageCount'	=> 全ページ数,
  'defaults'	=> あなたが最初に$htis->paginateで設定したoption,
  'options' => 今回実行されたoption
)
このパラメータを参照すれば、どのような結果になったかの概略を知ることが出来る。

表示

上記でようやく、データが揃った。そのページの表示は通常と同じ。
あとは pre << 1 | 2 | 3 | >>nextみたいな表示は、viewでpaginatorヘルパーを使用する。
その例は、こちら。PagenatorでPaginateしてみた。

*1 : 最終ページよりも大きい数値を指定した場合は、last指定と同じとなる。

*2 : orderの場合はorder=array('key'=>'direction')で指定しなければならない。

*3 : findAllと同じ形式

*4 : モデル名でもよいし、オブジェクトそのままでもよい。省略時は自分のモデル。

*5 : モデル名.アソシエーション名とすることもできるようだ(効果よくわかりません)

*6 : モデル名.フィールド名としての指定も可

*7 : 例:array('value'=>'5')

*8 : whitelistは、URLから渡されたパラメータのうち、有効にするキーを設定する。これを設定しない場合は、「sort(order),limit(show),page」以外のキーは無効となる。セキュリティを考えれば、わかる人以外は、ここを設定してはいけない。引数として渡す場合は、この設定をしなくても処理してくれる。あくまでもURLからの入力に対してものである。

*9 : ただし、ページ指定とlimitは強制的に、1と20にデフォルト設定されている。


名前:  非公開コメント   

  • TB-URL  http://www.cpa-lab.com/tech/053/tb/
  • CakePHP使い方 CPA-LABテクニカル spok
    Paginatorの使い方(データ抽出編)Paginatorの使い方2(表示編)
  • Paginator参考リンク集 CakePHPを本気で勉強
    CakePHP1,2にはページングの機能があると聞き使ってみることに。始めて利用してみましたが、便利すぎますね。自分でComponentにページングの関数を書いていましたが馬鹿馬鹿しくなってしまいますよ。 以下はPaginatorを使用する上で参考になっ...