CakePHP2.1でページネーション(実践編その6)

データベースのデータも数が多くなりすぎると1ページで表示するには不都合が生じます。そこで、今日は、CakePHPのPaginatorヘルパーを使って、ページネーションをする方法を勉強したいと思います。

1. CakePHPのPaginatorヘルパーは、コントローラ内の$helpersプロパティにデフォルトで登録されていますので、自前で登録することなく用いることが出来ます。試しにCollectionController.phpのindexアクションのデータをセットする箇所を下記のように修正してみます(①→②)。

①$this->set(‘Collections’,$data);

②$this->set(‘Collections’,$this->paginate());

2. たったこれだけ修正するだけで、今まで全データ表示されていたのが、20行しか表示されなくなりました。ただ、このままでは、残りのデータが閲覧できませんので、index.ctpを下記のように修正します。

app/View/Collection/index.ctp

<h1>私のコレクション</h1>
 <div class="paging">
 <?php
 echo $this->Paginator->prev('< 前へ', array(), null, array('class' => 'prev disabled'));
 echo $this->Paginator->numbers(array('separator' => ''));
 echo $this->Paginator->next('次へ >', array(), null, array('class' => 'next disabled'));
 ?>
 </div>
 <table cellpadding="0" cellspacing="0">
 <tr>
 <th><?php echo "ID";?></th>
 <th><?php echo "タイトル";?></th>
 <th><?php echo "作成日";?></th>
 <th><?php echo "更新日";?></th>
 <th><?php echo "コード番号";?></th>
 <th><?php echo "保管場所";?></th>
 </tr>
 <?php
 foreach ($Collections as $row): ?>
 <tr>
 <td><?php echo h($row['Collection']['id']); ?>&nbsp;</td>
 <td><?php echo $this->Html->link($row['Collection']['title'],array('action'=>'edit',h($row['Collection']['id'])));?>&nbsp;</td>
 <td><?php echo h($row['Collection']['created']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['modified']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['col_code']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['save_space']); ?>&nbsp;</td>
 </tr>
<?php endforeach; ?>
 </table>

3. それでは、ブラウザで確認してみます。URLが勝手に書き換えられています。

http://ドメイン名/Collection/→http://ドメイン名/Colleciton/index/page:1

4. ページ番号か次へをクリックすることにより2ページ目へ移動しました。URLも切り替わっています。

5. このようにCakePHPのPaginatorヘルパーはとても便利なのですが、自分の好きなように設定するにはどうすればいいのでしょう。これもとても簡単です。コントローラ内の$paginateに配列で条件を与えるだけでいいのです。下記に設定例を記述します。

public $paginator = array(
 'モデル名' => array(
 'fields' => array('フィールド1,フィールド2,フィールド3),
 'conditions' => array('フィールド[演算子] => 値),
 'limit' =>値,
 'order' => array('フィールド' => 'asc' 又は'desc'),
 ));

6. それでは実際にコントローラの最上部にをPaginatorの設定を追加挿入します。

app/Controller/CollectionController.php

<?php
class CollectionController extends AppController{
 //Paginationの設定
 public $paginate = array(
 //モデルの指定
 'Collection' => array(
 //1ページ表示できるデータ数の設定
 'limit' =>5,
 //データを降順に並べる
 'order' => array('id' => 'desc'),
 ));
 public function index(){
 //リクエストがPOSTの場合
 if($this->request->is('post')){
 //Formの値を取得
 $title=$this->request->data['Search']['title'];
 //POSTされたデータを曖昧検索
 $data=$this->Collection->find('all',array(
 'conditions'=>array('title like'=>'%'.$title.'%')));
 $this->set('Collections',$data);
 }else{ //POST以外の場合
 //Collectionモデルから全てのデータを検索
 $data=$this->Collection->find('all');
 //データをPaginatorへセット
 $this->set('Collections',$this->paginate());
 }
 }
(以下省略)

7. ブラウザで確認してみます。1ページの表示数が5件に変更になり、データが降順に並んでいます(画像では昇順となっていますが、実際には降順です)。

8. 最後にフィールド名をクリックするだけで昇順、降順を変更できるようにしたいと思います。index.ctpを下記のように修正します。

app/Collection/index.ctp

<h1>私のコレクション</h1>
 <div class="paging">
 <?php
 echo $this->Paginator->prev('< 前へ', array(), null, array('class' => 'prev disabled'));
 echo $this->Paginator->numbers(array('separator' => ''));
 echo $this->Paginator->next('次へ >', array(), null, array('class' => 'next disabled'));
 ?>
 </div>
 <table cellpadding="0" cellspacing="0">
 <tr>
 <th><?php echo $this->Paginator->sort('id','ID');?></th>
 <th><?php echo $this->Paginator->sort('title','タイトル');?></th>
 <th><?php echo $this->Paginator->sort('created','作成日');?></th>
 <th><?php echo $this->Paginator->sort('modified','更新日');?></th>
 <th><?php echo "コード番号";?></th>
 <th><?php echo "保管場所";?></th>
 </tr>
 <?php
 foreach ($Collections as $row): ?>
 <tr>
 <td><?php echo h($row['Collection']['id']); ?>&nbsp;</td>
 <td><?php echo $this->Html->link($row['Collection']['title'],array('action'=>'edit',h($row['Collection']['id'])));?>&nbsp;</td>
 <td><?php echo h($row['Collection']['created']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['modified']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['col_code']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['save_space']); ?>&nbsp;</td>
 </tr>
 <?php endforeach; ?>
 </table>

9. フィールド名をクリックするたびに、昇順、降順が切り替わるようになりました。これは便利ですね。

10. indexアクションをページネーションで表示するように修正していますので、先日作成したseachアクションとsearch.ctpも修正したいと思います。searchアクションとsearch.ctpを下記のように修正します。

app/Controller/CollectionController.php

public function search(){
 //リクエストがPOSTで送られたデータが空白で無ければ
 if($this->request->is('post') && $this->request->data['Search']['title']!=""){
 //Formの値を取得
 $title=$this->request->data['Search']['title'];
 //POSTされたデータを曖昧検索
 $data=$this->Collection->find('all',array(
 'conditions'=>array('title like'=>'%'.$title.'%')));
 $this->set('Collections',$data);
 }else{ //POST以外の場合
 //Collectionモデルから全てのデータを検索
 $data=$this->Collection->find('all');
 //データをセット
 $this->set('Collections',$data);
 }
 }

app/View/Collection/search.ctp

<h1>検索</h1>
<?php
 echo $this->Form->create('Search',array());
 echo $this->Form->input('title');
 echo $this->Form->end('検索');
?>
<?php if($this->request->is('post') && $this->request->data['Search']['title']!=""){?>
 <table cellpadding="0" cellspacing="0">
 <tr>
 <th><?php echo "ID";?></th>
 <th><?php echo "タイトル";?></th>
 <th><?php echo "種別";?></th>
 <th><?php echo "作成日";?></th>
 <th><?php echo "コード番号";?></th>
 <th><?php echo "保管場所";?></th>
 </tr>
 <?php foreach ($Collections as $row): ?>
 <tr>
 <td><?php echo h($row['Collection']['id']); ?>&nbsp;</td>
 <td><?php echo $this->Html->link($row['Collection']['title'],array('action'=>'edit',h($row['Collection']['id'])));?>&nbsp;</td>
 <td><?php echo h($row['ColAssort']['as_name']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['created']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['col_code']); ?>&nbsp;</td>
 <td><?php echo h($row['Collection']['save_space']); ?>&nbsp;</td>
 </tr>
<?php endforeach; ?>
 </table>
<?php };?>

11. ブラウザで確認してみます。『愛』と入力すると検索窓の下に一覧が表示されるようになりました。

複合語検索

12. スペースキーを挟んでの複数語句による検索について調べてみたいと思います。まず、preg_split()関数で、検索文字を空白で分割し、それぞれを配列に代入します。代入した配列を1つずつ取り出し配列の数だけ検索条件を作成して、再び配列に代入します。最後に作成した配列をfindメソッドのconditionsオプションに値を渡すことで複合語検索が出来ます。

13. searchアクションを下記のように修正します。

app/Controller/CollectionController.php

public function search(){
 //リクエストがPOSTの場合
 if($this->request->is('post') && $this->request->data['Search']['title']!=""){
 //Formの値を取得
 $title=$this->request->data['Search']['title'];
 //検索文字を空白(全角又は半角)で区切って配列$keywordsに代入
 $keywords=preg_split("/ |\\s/",$title);
 //配列$keywordsの数だけ繰り返して検索条件を$conditionsに代入
 foreach($keywords as $keyword){
 $conditions[]="title like '%$keyword%'";
 }
 //POSTされたデータを曖昧検索
 $data=$this->Collection->find('all',array(
 'conditions'=>$conditions
 ));
 //データをセット
 $this->set('Collections',$data);
 }
 }

14.  ブラウザで確認してみます。『愛』と『人』の間にスペースを挿入して検索をかけると2件のデータが検出できました。

本日のコード解説

$this->Paginator->prev(‘表示文字列’,オプション配列,無効時文字列,無効時オプション配列)

『戻る』リンクを作成します。現在より1少ないページ番号へリンクすることが出来ます。第一引数は表示する文字列を指定します。(例:『<<』『<<前へ』)第2引数は、リンクタグに付加するオプションを配列で指定します。第3引数はリンク無効時の文字列を指定します。初期値はnullです。第4引数はリンク無効時のリンクタグに付加するオプションを指定します。今回はクラスに『prev disabled』を指定しています。

$this->Paginator->numbers(‘オプション配列’)

ページ数を指定するリンクを生成します。表示するページ番号の個数や『最初へ』『最後へ』リンクなども制御できます。オプションで設定可能なパラメータを下記に記述します。

  • model
    モデル名を指定します。省略するとデフォルトのモデル名が指定されます。
  • tag
    各パーツを区切るタグを指定します。初期値は’span’です。
  • before
    各パーツの前に表示する文字列を指定します。初期値はnullです。
  • after
    各パーツの後に表示する文字列 を指定します。初期値はnullです。
  • separator
    区切り文字を指定します。
  • first
    文字列を指定することで『最初へ』リンクが可能な場合に、その文字列でリンクを生成します。数字を与えると最初からその数分のリンクを必ず表示します。
  • last
    文字列を指定することで『最後へ』リンクが可能な場合に、その文字列でリンクを生成します。数字を与えると最初からその数分のリンクを必ず表示します。
  • modulus
    表示するページ番号の個数を指定します。5ページ表示したい場合は4を指定します。

$this->Paginator->next(‘表示文字列’,オプション配列,無効時文字列,無効時オプション配列)

ページの『進む』リンクを生成します。現在ページより1ページ多いページ番号にリンクすることが出来ます。第一引数は表示する文字列を指定します。(例:『>>』『次へ>>』)第2引数は、リンクタグに付加するオプションを配列で指定します。第3引数はリンク無効時の文字列を指定します。初期値はnullです。第4引数はリンク無効時のリンクタグに付加するオプションを指定します。今回はクラスに『next disabled』を指定しています。

$this->Paginator->sort(‘リンク文字列’,’キー’,’オプション配列’)

ソート用のリンクを作成します。クリックすると、ソート順がそのキー(フィールド)になります。再度クリックするとソート方向が変わります。

本日は以上です。

このエントリーを含むはてなブックマーク Buzzurlにブックマーク livedoorクリップ Yahoo!ブックマークに登録

トラックバック&コメント

この投稿のトラックバックURL:

トラックバック

  1. […] を空白で区切って配列$conditionsに代入します。 findメソッドはconditionsに配列で条件を渡せば 複数の条件でデータを取得してくれます。 (参考) CakePHP2.1でページネーション(実践編その6) […]

コメント


コメントをどうぞ

このページの先頭へ