$this->paginate = array('limit' => 10, 'page' => 1);
$this->paginate(MODEL_NAME, Mixed);
こんな一行で勝手に10データ分ずつページネーションやってくれる優れもの。
大変便利な機能なんですけど、一つ欠点があります。
例えば、
ID | user_id | login_date |
---|---|---|
1 | 1 | 2008-02-29 |
2 | 1 | 2008-03-01 |
3 | 2 | 2008-02-29 |
4 | 3 | 2008-02-29 |
こんな「logs」なんつーテーブルがあったとします。
ここで、user_idごとにlogin回数を集計したいとなった場合、GROUP BY 句を使う必要があります。
そのときにController::paginateメソッドではうまくページネーションすることができなくなってしまうというわけです。
うーむ、ここばっかりは自前でページネーション作るしかないかぁ。がっくし、と少し肩を落としながら該当部分のソースをごろごろ眺めていると、
cake/libs/controller/controller.php : LINE 957
if (method_exists($object, 'paginateCount')) {
$count = $object->paginateCount($conditions, $recursive);
} else {
$count = $object->findCount($conditions, $recursive);
}
$pageCount = intval(ceil($count / $limit));
となってました。
どうやらモデル内にpaginateCountというメソッドを用意してあげて、そいつが適切なカウント数を返してあげればGROUP BY句が入っていようが、きちんとページネーションしてくれるというわけでした!
モデル名はLogということにして試しに書いてみるとこんな感じ。
app/model/log.php
class LogModel extends AppModel {
var $name = "Log";
function paginateCount($conditions, $recursive) {
$result = $this->query('SELECT Log.user_id FROM logs as Log WHERE ' . $conditions[1]);
return count($result);
}
}
今回の検証ではconditionsは配列になっていて、[1]にController::paginateに渡したWHERE句が入っていました。
この辺はもうちょっと調べなきゃです。
と、このメソッドをモデルに突っ込んでおくだけで集計後の値でカウントしたいようなテーブルにおいてもpaginateが使用できます。なかなか素敵ですね。
ただ、
return count($result);
がなんかかっこわるいですw
SELECT COUNT ( SELECT Log.user_id FROM logs as Log WHERE HOGE GROUP BY Log.user_id );
とかいけそうな気がしたけど駄目でしたorz
あれー、こういう書き方ってダメなんだっけ。。
4 件のコメント:
グダグダしてすみません…
やっぱりこれで
$result = $this->find($conditions, 'count(DISTINCT Log.user_id)', null, $recursive);
return $result[0]['count'];
最後の$result[0]がややマジックナンバーになって解りづらいですよねぇ^^;
わーい。こんなところでcohtanに助けられたー♪
まじ助かった。
コメントを投稿