18 ноября 2007 г.

Pagination в CakePHP 1.2. Небольшая хитрость

Этот пост устарел! Читайте по ссылке исправленную и сильно переработанную версию!

This is totally outdated article! Follow the link to see a more complete version! Sorry. The newwer post in russian too.

Как уже писал, Containable behaivior, который отлично справляется с задачей выборки только нужных для данного действия (action). И при небольшой модификации отлично работает с методом pagination. Однако есть одна неприятная вещь, опять же связанная с тем, что pagination вызывает последовательно 2 метода модели — сначала для подсчета количества записей, а потом для выборки.

При попытке подсчитать количество записей у модели с большим количеством связей, paginator делает SQL запрос SELECT COUNT(*) со всеми положенными JOIN'ами, что при больших объемах данных существенно увеличивает время выполнения запроса. Особенно, если при этом еще и сортировку делать надо. Этот факт сильно раздражает, если в итоге нужно всего-лишь количество записей в основной модели.

Выход есть. Разглядывая код метода paginate, обнаружил, что Cake пытается сначала вызвать метод paginateCount, а если его нет, то вызывает findCount.

Ура! Определяем в модели метод paginateCount:


function paginateCount($conditions, $recursive)
{
  return $this->findCount($conditions, -1);
}

и готово!

Теперь paginate считает записи только в нужной нам модели, не вызывая JOIN'ов, а возвращает записи со всеми нужными дополнительными данными.