
前回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側の記述が抜けておりました。
申し訳ございません。
記事を修正しましたので、そちらをご確認ください。
ありがとうございました。