スポンサードリンク
前回CakePHPで検索ページを作って
データを表示させました。
しかし、データ量が多くなると
検索結果が多くなり
さらに、SQLの処理も遅くなってしまうため
Limitを付けて検索させたいと思いました。
なら、簡単にページネーションまで作ってくれる
CakePHPのPagenateを使って表示するようにしました。
スポンサードリンク
CakePHPのページネーションを設定
前回の検索機能にページネーションを付けます。
まずはページネーションの設定です。
(例)Controller/PostsController.php
//Paginationの設定
public $paginate = array( //モデルの指定 'Post' => array( //1ページ表示できるデータ数の設定 'limit' => 20, ) );
次にアクション部分の設定です。
前回の検索機能のコントローラー
(例)Controller/PostController.php
public function search(){ //リクエストがPOSTで送られたデータが空白で無ければ if($this->request->is('post') && $this->request->data['Post']['title'] != ""){ //Formの値を取得 $title = $this->request->data['Post']['title']; //検索文字を空白(全角又は半角)で区切って配列$keywordsに代入 $keywords = preg_split("/ |\\s/",$title); //配列$keywordsの数だけ繰り返して検索条件を$conditionsに代入 foreach($keywords as $keyword){ $conditions[] = "title like '%$keyword%'"; } //POSTされたデータを曖昧検索 $data=$this->->find('all',array( 'conditions' => $conditions )); $this->set('datas',$data); } }
これを、下記のように変更します。
public function search(){ //リクエストがPOSTで送られたデータが空白で無ければ if($this->request->is('post') && $this->request->data['Search']['title'] != ""){ //Formの値を取得 $title = $this->request->data['Post']['title']; //検索文字を空白(全角又は半角)で区切って配列$keywordsに代入 $keywords = preg_split("/ |\\s/",$title); //配列$keywordsの数だけ繰り返して検索条件を$conditionsに代入 foreach($keywords as $keyword){ $conditions[] = "title like '%$keyword%'"; } $data = $this->paginate($conditions); $this->set('datas',$data); } }
pagenateに検索条件を指定してあげればいいだけです。
pagenateメソッドの引数に条件を配列で指定すると
ページネーションの機能を使って検索結果を表示できます。
また、アクションの前のpagenate変数にオーダーなどの指定もできますが、
アクションによって並び替えをしたい場合は
public function search(){ //リクエストがPOSTで送られたデータが空白で無ければ if($this->request->is('post') && $this->request->data['Search']['title'] != ""){ //Formの値を取得 $title = $this->request->data['Post']['title']; //検索文字を空白(全角又は半角)で区切って配列$keywordsに代入 $keywords = preg_split("/ |\\s/",$title); //配列$keywordsの数だけ繰り返して検索条件を$conditionsに代入 foreach($keywords as $keyword){ $conditions[] = "title like '%$keyword%'"; } //作成日の新しい順に並べ替える $this->paginate = array( 'order' => array('created' => 'DSEC') ); $data = $this->paginate($conditions); $this->set('datas',$data); } }
このようにするとページネーションを
各アクションごとに条件を指定できます。
ページを変えても同じ結果が出るようにする
最初の方法だとページが変わったときに
1ページ目のみしか検索結果が表示されなくなります。
2ページ目以降も同じ結果が出るようにするために
検索条件をセッションに入れるようにします。
public function search($page = null, $sort = null, $direction = null){//ページのパラメータを取る //リクエストがPOSTで送られたデータが空白で無ければ if($this->request->is('post') && $this->request->data['Search']['title'] != ""){ //Formの値を取得 $title = $this->request->data['Post']['title']; //session用 $search['title'] = $title; //検索文字を空白(全角又は半角)で区切って配列$keywordsに代入 $keywords = preg_split("/ |\\s/",$title); //配列$keywordsの数だけ繰り返して検索条件を$conditionsに代入 foreach($keywords as $keyword){ $conditions[] = "title like '%$keyword%'"; } //検索条件をセッションに保存 if($this->Session->check('conditions')){ $this->Session->delete('conditions'); //古いのは削除 } if($this->Session->check('search')){ $this->Session->delete('search'); //古いのは削除 } $this->Session->write('conditions', $conditions); $this->Session->write('seach', $search); //作成日の新しい順に並べ替える $this->paginate = array( 'order' => array('created' => 'DSEC') ); $data = $this->paginate($conditions); $this->set('datas',$data); }else{ if($this->Session->check('conditions')){ //パラメータがなければ新しい検索のため削除 if(empty($this->params['named']['page']) && empty($this->params['named']['sort']) && empty($this->params['named']['direction'])){ $this->Session->delete('conditions'); $this->Session->delete('search'); }else{ $conditions = $this->Session->read('conditions'); $search = $this->Session->read('search'); //作成日の新しい順に並べ替える $this->paginate = array( 'order' => array('created' => 'DSEC') ); $data = $this->paginate($conditions); $this->set('datas', $data); $this->set('search', $search); } } }
検索ボタンを押したとき
//検索条件をセッションに保存 if($this->Session->check('conditions')){ $this->Session->delete('conditions'); //古いのは削除 } if($this->Session->check('search')){ $this->Session->delete('search'); //古いのは削除 }
まず検索ボタンを押した場合に
検索条件をセッションに保存します。
その際に、検索キーワードもセッションに入れておきます。
2ページ目とかに移動した場合に
フォームにキーワードが入っていた方が親切だと思うので・・・
セッションにデータを保存する前に
セッションに前の検索データがあるかを調べて
あれば削除してから、セッションに保存します。
検索条件をセッションに入れると
他のページへ行ってから検索ページに戻ると
検索条件が残ってるといけないので
ページの最初に来たときに
セッションに検索結果があれば削除するようにします。
ページを移動したときと最初に来たとき
if($this->Session->check('conditions')){ ・・・ 略 }else{ ・・・ 略
ページを移動したときと最初に検索ページに来たときは
まず、検索用のセッションがあるかないかを調べます。
無い場合は一番最初の状態なのでセッションがないです。
なので何もしません。
セッションがある場合はページ移動か以前検索した場合なので
ページ移動かどうかを調べます。
ページ移動の場合はパラメーターがあるので
パラメーターがあるかどうかを調べます。
まずは、パラメータを取得できるようにsearchメソッドの引数に
設定を追加しておきます。
public function search($page = null, $sort = null, $direction = null){//ページのパラメータを取る ・・・ 略
上記のようにしておくとページ番号や並び順などをパラメータとして取得できます。
if($this->Session->check('conditions')){ //パラメータがなければ新しい検索のため削除 if(empty($this->params['named']['page']) && empty($this->params['named']['sort']) && empty($this->params['named']['direction'])){ $this->Session->delete('conditions'); $this->Session->delete('search'); }else{ ・・・ 略
ページ番号などのパラメータがなければ
ページ移動ではないので検索ページに新しく来たことになります。
なので、前回の検索条件を削除します。
if(empty($this->params['named']['page']) && empty($this->params['named']['sort']) && empty($this->params['named']['direction'])){ $this->Session->delete('conditions'); $this->Session->delete('search'); }else{ $conditions = $this->Session->read('conditions'); $search = $this->Session->read('search'); //作成日の新しい順に並べ替える $this->paginate = array( 'order' => array('created' => 'DSEC') ); $data = $this->paginate($conditions); $this->set('datas', $data); $this->set('search', $search);
パラメーターのデータがあればページ移動なので
セッションの検索条件と検索キーワードをセッションから読んで
変数にセットします。
スポンサードリンク
ビューファイルの調整
コントローラーは調整できたので
次にフォームに検索キーワードを入れるようにします。
検索フォームの部分に以下のように変えます。
(例)View/Posts/search.php
<?php if(!empty($search)){ $title = $search['title']; }else{ $title = ""; } echo $this->Form->create('Post', array('action'=>'search')); echo $this->Form->input('title', array('label' => 'タイトル名を入れてください', 'default' => $title)); echo $this->Form->end('検索'); ?>
これでページ移動しても
検索フォームに検索キーワードが入力された状態になります。
スポンサードリンク
はじめまして、少々気になったので、ぶしつけながら失礼します。
コントローラーの22行目
$this->Session->write(‘search’, $search);
この$searchですが、何が入っているのでしょうか?
設定されているところが見当たらなかったので、質問させていただきます。
>hiroさん
コメントありがとうございます。
ご質問のあった、$searchですが
この記事の内容にはいらない変数です。
元々、作ったものに記述してあったものが残ったままでした。
ややこしくてすみません。
作ったものでは
$searchに検索に使用したキーワードを入れるようにしています。
ページが変わっても、フォームは残したままにしているため
フォームに検索したキーワード表示させるために使っています。
この記事にはあるとややこしくなるため
修正しておきます。
ありがとうございました。
はじめまして。
1点確認ですが、
View/Posts/search.phpの3行目の$searchですが、どこで値を設定していますか?
controller側から、$searchに値を渡しているようには見えなかったもので質問しました。
>otakaさん
コメントありがとうございます。
ご質問の
>View/Posts/search.phpの3行目の$searchですが、どこで値を設定していますか?
ですが、Controller側の記述が抜けておりました。
申し訳ございません。
記事を修正しましたので、そちらをご確認ください。
ありがとうございました。