院生エンジニアのにっき

  • Change style to Blue
  • Change style to Red
  • Change style to Green
  • Change style to Pink

Paginator(4/18 修正)   2007-04-17

CakePHPの1.2ではBakeで作成したindexページに標準でページャーがついています。

ページャーの仕組みは、URLを「/controller_name/action_name/page:1/sort:field_name/direction:asc」(例:/mails/index/page:1/sort:date/direction:desc)などのようにして、URLをクリックするたびにdirectionがasc(昇順)かdesc(降順)かが切り替わります。

CakePHPなどどのフレームワークを使ってもそうなんですが、フレームワークは自動化が進むにつれてちょっとの変更が大変になりますorz....

当然CakePHPのページャーもしかりで、上の例のURLを/mails/index/2(「2」は例えばアカウントIDやカテゴリーIDなど、where句の絞込み条件とするための値と思ってください)のようなページに対してページャーを利用しようとするととても大変です。

  • 絞り込み条件の追加
  1. <?php
  2. function index($category_id){
  3.         $options = array();
  4.         if(isset($category_id) && is_numeric($category_id)){
  5.                 $options['conditions'] = 'Mail.category_id = '.$category_id;
  6.         }
  7.         $this->Mail->recursive = 1;
  8.         $this->paginate = am($this->paginate,$options);
  9.         $this->set('mails', $this->paginate());
  10. }
  11. ?>

これで表示されるページャーの絞り込み条件(category_id = n)を指定できました。上のソースはまぁ直感的にも言いたい事はわかるのではないでしょうか。


しかし問題は絞込み条件を指定した後で、絞り込み条件を指定した際に/views/index.ctpよりページを表示した際、ソート条件を切り替えるためのURLが未だに「/mails/index/page:1/sort:date/direction:desc」のままであることに気がつくかと思います。

mails_controller.phpに「$this->set('category_id',$category_id);」と指定して色々すればなんとかなるのかと試行錯誤したのですが、結局のところ


  1. <?php
  2. //mails_controller.php
  3. function index($category_id){
  4.         $this->Mail->recursive = 1;
  5.         if(isset($this->passedArgs['category_id'])){$id = $this->passedArgs['category_id'];}
  6.         $options = array();
  7.         $pager_options = array();
  8.         if(isset($id) && is_numeric($id)){
  9.                 $options['conditions'] = 'Mail.category_id = '.$category_id;
  10.                 $pager_options['url'] = array('category_id'=>$id);
  11.         }
  12.         $this->paginate = am($this->paginate,$options);
  13.         $this->set('options',$pager_options);
  14.         $this->set('mails', $this->paginate());
  15. }
  1. //mails/index.ctpの該当行を変更
  2. <?php echo $paginator->sort('field_name',null,$options);?>

で対応できるかと思います(この手法が一般的で最適かどうかはわかりませんが、現状ではこうするしかなさそうです)。

何をしているかと言うと、mails_controller.phpにて$idに$this->passedArgs['category_id']を代入していますがここがミソです。passedArgsは、上のURLでいえばdirection:descの部分からarray('direction'=>'desc')を作成し、代入されたクラス変数なので、そこにcategory_idを「category_id:$id」となるようにURLを書き換えさせています。

それでindex.ctp側にて$paginator->sortの第三引数に$optionsとしてarray('url'=>array('category_id'=>$id));を用いることによってページャーの切り替え用URLに「category_id:$id」が追加されます。


・・・とまぁ手法としてはこれでいいとは思いますが、スマートではないですね。


現在CakePHPの1.2系列はまだα版ですが、stable版になる頃にはそのまま$paginator->sort('field_name')でURLがそのまま指定できたらと思います。


-----------------------------

  • 修正

最後のサンプルコードで

  1. <?php echo $paginator->sort('field_name',null,$options);?>

をindex.ctpに書くとありましたが、全てのページャークラスに$optionsの引数を渡すよりスマートな方法がありました。

  1. <?php echo $paginator->options($options);
  2. <table><tr>
  3. <th><?php echo $paginator->sort('field_name1');?></th>
  4. <th><?php echo $paginator->sort('field_name2');?></th>
  5. ・・・・・
  6. </tr><table>
  7. ?>

$paginator->optionsで、全てのリンクにオプションを追加することができます。

「Sets default options for all pagination links」とコメントにもあります。



コメントを書く