joinやサブクエリ、集合演算などを含む複雑な検索を行う場合、
- まず検索条件にマッチする全行のidを求め、
- Model.id IN (1で求めた全id) という条件で一覧表示に使うデータを取得する
という手順を踏んだ方が合理的なことがある。
この場合、1の段階で「検索条件にマッチする全行数」が判明するため、Paginationのために改めてCOUNTクエリを発行するのは完全に無駄である。CakePHP 1.2のPagination機能でこの無駄を回避するには、コントローラの $paginate プロパティに適当なキー(下例では numberOfRows)で件数を保存しておき、
$allIds = $this->Foo->find('all', array('fields' => 'DISTINCT Foo.id', 'conditions' => $complexCond)); $this->paginate['numberOfRows'] = $this->Foo->getNumRows();
対象となるモデルの paginateCount メソッドでその数値をそのまま返すようにする。
class Foo extends Model { function paginateCount($conditions=null, $recursive=0, $extra=array()) { if(isset($extra['numberOfRows'])) { return $extra['numberOfRows']; } $parameters = compact('conditions'); if ($recursive != $this->recursive) { $parameters['recursive'] = $recursive; } return $this->find('count', array_merge($parameters, $extra)); } }
$paginate の中で認識されないキーは、Model::paginate や Model::paginateCount の最後の $extra 引数として渡ってくる。