CakePHP2のPaginatorを検索でも使えるように
方法を知らなかったので1日失ったよ…
Paginatorを使ってページングを実現しつつ、Cakeのアソシエーションを使って複数テーブルを結合させつつ、検索機能の実装をする必要があったしようと思ってた。
アソシエーションをいくつも使っていると、発行されるsqlは1回ではなくなるようで、そうすると深い階層のデータ検索を行った時の結果行数の値がおかしな事になってた、みたい…?
色々調べた結果、以下の方法に辿り着いたよ。時間掛かったよ。。
$this->paginate = array( //表示するフィールドの指定をする。'*'で全部。 'fields' => '*' , //JOIN するテーブルの設定。 'joins' => array( array( 'type' => 'LEFT', 'alias' => 'Tag', 'table' => 'tags', 'conditions' => array('Tag.id = Book.tag_id') ) ) 'conditions' => array( 'Book.name' => 'ABCD' ) ); $this->set('books',$this->Paginator->paginate());
フォームを使って絞込検索条件を指定しつつ、条件ごとにsqlを変えられるようにしてみた。
$joins = array(); $cond = array(); if ($this->request->is('post')) { /* フォームからの値。(例) $this->data['category_name'] = 'マンガ'; */ if(!empty($this->data['category_name'])){ //category名の指定があったら、categoryテーブルをJOINする $join = array( 'type' => 'LEFT', 'alias' => 'Category', 'table' => 'categories', 'conditions' => array('Category.id = Book.category_id') ); //$joins配列にプッシュ array_push($joins,$join); //検索条件を追加 $cond['Category.name'] = $this->data['category_name']; } /* フォームからの値。チェックボックスとか。(例) $this->data['tag_ids'] = array(2,5,14,11); */ if(!empty($this->data['tag_ids'])){ //tag_idの指定があったら、tagテーブルをJOINする $join = array( 'type' => 'LEFT', 'alias' => 'Tag', 'table' => 'tags', 'conditions' => array('Book.tag_id = Tag.id') ); //$joins配列にプッシュ array_push($joins,$join); //検索条件を追加 $cond['Tag.id'] = $this->data['tag_ids']; } //条件を設定 $this->paginate = array( 'fields' => '*' , 'joins' => $joins, 'conditions' => $cond ); $this->set('books',$this->Paginator->paginate()); }
こんな感じで。
ただ、これだけだとページングした時に検索条件が引き回されないので、getのパラメータを使うとか、sessionを使うとかしないといけないです。