paginator.php

Posted by muchag | CakePHP | 2011-05-22 (日) 0:18:55

Paginator ヘルパーの利用法。

Paginator ヘルパーについては、
少なくとも私が探した限りでは優しい解説がない。

だからよくわからない。
分かったことから少しずつ記述。
よって、不確かな記述が多い

【環境】
[CakePHP] 1.3.8

 

cake ディレクトリ\libs\view\helpers\paginator.php

The CakePHP 1.3 Book
4.9 ページ付け(Pagination)
7.8 Paginator
 

コントローラ
定義

ページネータはコントローラで定義する。

定義場所はプロパティかメソッド、どちらでもよい。
複数のアクションで利用したければプロパティ。
単一のアクションで利用するならメソッド内でもよい。
 

プロパティ(フィールド)
  1. class RecipesController extends AppController {
  2.  
  3.     var $paginate = array(
  4.         'limit' => 25,
  5.         'order' => array(
  6.             'Post.title' => 'asc',
  7.             ),
  8.         );
  9. }

 

メソッド(アクション)
  1. class RecipesController extends AppController {
  2.  
  3.     function list_recipes() {
  4.  
  5.         $this->paginate = array(
  6.             'limit' => 25,
  7.             'order' => array(
  8.                 'Post.title' => 'asc',
  9.                 ),
  10.             );
  11.     }
  12. }

 

複数のモデルに定義

定義配列の階層を1つ増やし、モデル毎に定義する。

  1. class RecipesController extends AppController {
  2.     var $paginate = array(
  3.         'Recipe' => array (...),
  4.         'Author' => array (...)
  5.         );
  6. }

 

内容

定義する内容は

  • conditions
  • fields
  • order
  • limit
  • page
  • contain
  • recursive

で、モデルでデータを取得するときの設定に似ている。
The CakePHP 1.3 Book:3.7.3 データを取得する
 

conditions

WHERE 句。配列 で指定。

  1. 'conditions' => array(
  2.     'Model.field' => $thisValue,
  3.     ),

 

fields

抽出指定カラム名。配列 で指定。

  1. 'fields' => array(
  2.     'Model.field1',
  3.     'DISTINCT Model.field2',
  4.     ),

 

order

ソート指定。 or 配列 で指定。
必ず 指定しなければならない。
(確かめたわけではないが、マニュアルにそう書いてあった)

  1. 'order' => 'Post.title asc',
  1. 'order' => array(
  2.     'Post.title asc',
  3.     ),
  1. 'order' => array(
  2.     'Post.title' => 'asc',
  3.     ),

 

limit

1ページ当たりの表示レコード数。 で指定。

  1. 'limit' => 25,

 

page

で指定。

  1. 'page' => n,

 

contain

 

recursive

アソシエーション階層レベル。 で指定。

  1. 'recursive' => 1,

 

ビューへの受け渡し
  1. class RecipesController extends AppController {
  2.  
  3.     function list_recipes() {
  4.  
  5.         $this->paginate = array(
  6.             /* 略 */
  7.             );
  8.  
  9.         $data = $this->paginate('Recipe');
  10.         $this->set('data', $data););
  11. または
  12.         $this->set('data', $this->paginate('Recipe'));
  13.     }
  14. }

 

ビュー
メソッド

The CakePHP 1.3 Book:7.8.1 メソッド
私の頭は相当悪いらしく、マニュアルを読んでもサッパリ理解できない。
大体、メソッドが全然足りないのだが、どこにあるかすら見つけられない。
(あんまり真面目には探してないけど・・・)

プロの方々はこれで理解できるわけで、尊敬する。。。

で、他のサイトも参考にしつつ・・・。
 

ページリンク表示
  1. echo $paginator->numbers($options = array());

第1引数:オプション配列。省略可
これで、以下のような表示をしてくれる。
1 | 2 | 3
 

前へ、後ろへ
  1. echo $paginator->prev($title = '<< Previous', $options = array(), $disabledTitle = null, $disabledOptions = array());
  2. echo $paginator->next($title = 'Next >>', $options = array(), $disabledTitle = null, $disabledOptions = array());
  3.  
  4. echo $paginator->prev('前へ');
  5. echo $paginator->next('次へ');

第1引数:表示文字列
第2引数:オプション配列。省略可
第3引数:対象ページが存在しない場合の表示文字列。省略可
第4引数:対象ページが存在しない場合のオプション配列。省略可
 
$options のデフォルトは以下のようになっている。

  1. $_defaults = array(
  2.     'url' => array(), 'step' => 1, 'escape' => true,
  3.     'model' => null, 'tag' => 'span', 'class' => strtolower($which)
  4. );

残りは未解読。

参考サイトに、先頭ページでは「前へ」を、末尾ページでは「後へ」を
表示させないデモがある。
echo $paginator->prev(‘前へ’, null, ‘ ‘);
とすることで実現できたが、第3引数には半角スペースを入れてある。
気持ちが悪い・・・。

でも、” や null ではだめだった。
 

先頭へ、末尾へ
  1. echo $paginator->first($first = '<< first', $options = array());
  2. echo $paginator->last($last = 'last >>', $options = array());
  3.  
  4. echo $paginator->first('先頭へ');[
  5. echo $paginator->last('末尾へ');

第1引数:表示文字列
第2引数:オプション配列。省略可
 
$options のデフォルトは以下のようになっている。

  1. array(
  2.     'tag' => 'span',
  3.     'after'=> null,
  4.     'model' => $this->defaultModel(),
  5.     'separator' => ' | ',
  6. ),

未解読。
 

現在のページ番号
  1. echo $paginator->current($model = null);

 

ページング諸情報
  1. echo $paginator->counter($options = array());

以下のような定義済み定数があり

  • %page% – 現在表示しているページ
  • %pages% – ページ総数
  • %current% – 表示している現在のレコード数
  • %count% – 結果セットのレコード総数
  • %start% – 表示している最初のレコードの数
  • %end% – 表示している最後のレコードの数

以下のようにしてページング情報を出力可能。

  1. echo $paginator->counter(array(
  2.     'format' => 'Page %page% of %pages%,
  3.             showing %current% records out of %count% total,
  4.             starting on record %start%, ending on %end%'
  5.             )
  6. );

 

ソートリンク
  1. echo $paginator->sort($title, $key = null, $options = array());
  2.  
  3. echo $paginator->sort('ID', 'id'); // 例

第1引数:表示文字列
第2引数:ソート対象カラム名
第3引数:オプション配列。省略可
 

リンク作成
  1. echo $paginator->link($title, $url = array(), $options = array());

 

URL
  1. echo $paginator->url($options = array(), $asArray = false, $model = null);

 

オプション定義
  1. echo $paginator->options($options = array());

 
他にもまだメソッドはある。
けど、ひとまず力尽きた。 🙄
 

GROUP BY との併用

paginator を利用する際の $params に ‘group’ を指定すると
paginateCount 関数が誤動作を起こすので
モデルにて paginateCount 関数をマージしないといけない。
The CakePHP 1.3 Book:4.9.4 カスタムしたクエリによるページ付け

マニュアルにあるのは PostgreSQL 用のコードなので
MySQL 用をグーグル先生に聞いてみた。

以下引用コード。

  1. //GroupBy対策
  2. function paginateCount($conditions = null, $recursive = 0, $extra = array())
  3. {
  4.     $parameters = compact('conditions');
  5.  
  6.     $this->recursive = $recursive;
  7.  
  8.     $count = $this->find('count', array_merge($parameters, $extra));
  9.  
  10.     if (isset($extra['group'])) {
  11.  
  12.         $count = $this->getAffectedRows();
  13.     }
  14.  
  15.     return $count;
  16. }

当該モデルにこちらのコードを追加したところ
お蔭様で、意図通り動作した。

コードの中身を見るとマニュアルのコードと異なり SQL 文がないので
特に MySQL 用というわけでなく、汎用なのかも。
 

参考元サイト

gihyo.jp:CakePHPで高速Webアプリ開発 第15回 Paginationで面倒なページ繰り処理とおさらばしよう
typeOf ‘aki_mana’:Paginator (ver 1.3)
Garacter:CakePHP Note > コントローラー > ページング
Ks web Design:PaginateでGroupByするとpaginator->number()が表示されなくなる時の対処

CakePHP | 2011-05-22 (日) 0:18:55 |

コメントはまだありません »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment