スポンサードリンク

CakePHPのPaginateがとても便利で
色々な場所に使っているのですが、
重複したものを取り除いた場合に
ページ数が重複を取り除く前になってしまいます。
そのページ数を直す方法です。
スポンサードリンク
重複したものを省くGROUP BY
まず、Paginateを使う時にGROUP BYをしていします。
コントローラーで重複を省きたいカラムを設定します。
アクションごとに設定する場合は設定したアクション内に記述します。
$this->paginate = array( 'group' => array('company'), ); $data = $this->paginate();
これでPagenateすると
取得データはGROUP BYされています。
しかし、ページ数や取得件数がGROUP BYの前の結果になってしまい
ページ移動をするとエラーになります。
Paginatorで件数を取得しなおす
こちらに解決策がありました。
(参考)
Group Byしている時にpaginator->number()が表示されない件Add Star
GROUP BYをするモデル内で
paginateのオプションとして’group’が含まれていれば
getAffectedRowsをオーバーライドして
ページ数を取得しなおすという方法です。
Model.php
//ページネーションでGroup By使ったときのページ数 public function paginateCount($conditions = null, $recursive = 0, $extra = array()) { $parameters = compact('conditions'); $this->recursive = $recursive; $count = $this->find('count', array_merge($parameters, $extra)); if (isset($extra['group'])) { $count = $this->getAffectedRows(); } return $count; }
こうすると、paginateの設定で
GROUP BYを設定している場合は
ページカウンターがページ数を
取得しなおしてくれて
問題なく使えます。
スポンサードリンク
DISTINCTで試してみる
重複を取り除く方法としてDISTINCTもあります。
こちらでやった場合ですが、
GROUP BYと同じでページ数が重複を取り除く前のページ数になります。
こんな感じでDISTINCTを指定します。
$this->paginate = array( 'fields' => array('DISTINCT company'), ); $data = $this->paginate();
これをGROUP BYと同じ方法でやってみます。
こちらを参考にさせてもらいました。
(参考)
【cakePHP】重複を省いたPaginator
Model.php
public function paginateCount($conditions = null, $recursive = 0, $extra = array()) { $parameters = compact('conditions'); $this->recursive = $recursive; $extra['fields'] = 'DISTINCT '.$this->name.'.id'; // 重複削除 $count = $this->find('count', array_merge($parameters, $extra)); return $count; }
この方法でもページ数は重複を除いた数で出てきました。
が、
これだと、同じモデルを使ってPagenateしているアクションで
勝手にDISTINCTされてしまいます。
じゃあ、GRORP BYの時と同じように
fieldsで判断させればと思いまして、
Model.php
//ページネーションでGroup By使ったときのページ数 public function paginateCount($conditions = null, $recursive = 0, $extra = array()) { $parameters = compact('conditions'); $this->recursive = $recursive; $count = $this->find('count', array_merge($parameters, $extra)); if (isset($extra['fields'])) { $count = $this->getAffectedRows(); } return $count; }
こんな感じでextraでfieldsがあるときにとしてみました。
コントローラーにはDISTINCTを付けます。
$this->paginate = array( 'fields' => array('DISTINCT company'), ); $data = $this->paginate();
すると・・・
結果は重複が取り除かれているものの
ページ数は重複前のの状態です。
なぜだろうと思いましてPaginatorControllerの中身を見てみると
lib/Cake/Controller/Component/PaginatorController.php
//169行目らへん $extra = array_diff_key($options, compact( 'conditions', 'fields', 'order', 'limit', 'page', 'recursive' ));
ここを見るとオプション項目で
‘conditions’, ‘fields’, ‘order’, ‘limit’, ‘page’, ‘recursive’の
6つの項目は変数extraに渡されないようです。
なので、GROUP BYで判断させるものの方が
使い勝手がいいかと思います。
スポンサードリンク