Контент


Ko3 count_last_query()

Помните, в Kohana v2.3.4 был такой метод объекта Database? Если нет, то напомню — данный метод возвращал общее количество записей для предыдущего запроса. Например, выбрали 10 первых записей из выборки, а потом вызвали $this->db->count_last_query() и узнали, что всего записей 35. Стоп, скажете Вы! Ведь есть метод count_records(), который занимается тем же самым. Да, count_records() считает все записи, но count_last_query() учитывает все примененные условия последнего запроса (WHERE, HAVING и т.д.). Зачем это нужно? В первую очередь для модуля Pagination, ведь надо как-то вычислять общее количество страниц, а оно зависит именно от числа записей.

Так вот, в Ko3 такого метода нет. Почему — непонятно, хотя сделать его несложно. По сути просто берется текст последнего запроса и вырезаются модификаторы LIMIT и OFFSET. Вспоминаем лозунг «спасение утопающих — дело рук самих утопающих», и переносим метод count_last_query() из 2.3.4 в 3.0. У меня получилось вот так:

/**
 * Count the number of records in the last query, without LIMIT or OFFSET applied.
 *
 * @return  integer
 */
public function count_last_query()
{
	if ($sql = $this->last_query)
	{
		$sql = trim($sql);
		if (stripos($sql, 'SELECT') !== 0)
		{
			return FALSE;
		}
			if (stripos($sql, 'LIMIT') !== FALSE)
		{
			// Remove LIMIT from the SQL
			$sql = preg_replace('/sLIMITs+[^a-z]+/i', ' ', $sql);
		}
			if (stripos($sql, 'OFFSET') !== FALSE)
		{
			// Remove OFFSET from the SQL
			$sql = preg_replace('/sOFFSETs+d+/i', '', $sql);
		}
			// Get the total rows from the last query executed
		$result = $this->query
		(
			Database::SELECT,
			'SELECT COUNT(*) AS '.$this->quote_identifier('total_rows').' '.
			'FROM ('.$sql.') AS '.$this->quote_table('counted_results'),
			TRUE
		);
 
		// Return the total number of rows from the query
		return (int) $result->current()->total_rows;
	}
 
	return FALSE;
}

Закидываем это в файл APPPATH/classes/database.php, чтобы не редактировать системный класс Kohana_Database. Проверяем — должно работать. Если хочется, чтобы заработало и в ORM (обычно с Pagination используют именно ORM), надо создать в нем метод count_last_query(), где прописать вызов $this->_db->count_last_query(). Естественно, править надо не сам системный файл MODPATH/orm/classes/kohana/orm.php, а создать свой — APPPATH/classes/orm.php.

Вот и все. Пользуйтесь на здоровье :)

Google Bookmarks Digg Reddit del.icio.us Ma.gnolia Technorati Slashdot Yahoo My Web News2.ru БобрДобр.ru RUmarkz Ваау! Memori.ru rucity.com МоёМесто.ru Mister Wong

Опубликовано в Kohana3, напильник.

Теги: , , .


Комментарии (7)

Будьте в курсе обсуждения, подпишитесь на RSS ленту комментариев к этой записи.

  1. Satisfaction пишет:

    Кхм странно что его нет в третей линейке. А я сижу себе в 2.3.4 и радуюсь :D

  2. Werewolf пишет:

    Господи, почему нельзя просто использовать SQL_CALC_FOUND_ROWS()/FOUND_ROWS()

  3. BIakaVeron пишет:

    @Werewolf
    Это решение специфично для MySQL. Кроме того, требуется заранее модифицировать свой запрос (добавить SQL_CALC_FOUND_ROWS). Помните, что класс Database абстрагируется от конкретной СУБД.

  4. ANT пишет:

    count_last_query генерирует очень тяжелый запрос с точки зрения SQL. Любой оптимизатор застрелиться увидев такой запрос :)

  5. BIakaVeron пишет:

    Оптимизация и универсализм вообще понятия малосовместимые :) Вообще, как минимум под MySQL можно попытаться данный запрос урезать.

  6. Иван пишет:

    Werewolf — Согласен я тоже его использую

  7. Максим Нагайченко пишет:

    Согласен с Werewolf , проект у меня под Мускуль, юзаю такую фичу.

    Правда если перейду на другу СУБД, то поплачусь. Хорошо, что в 3,0,5 вышла такая фича. Теперь можно сделать переключение на SQL_CALC_FOUND_ROWS() или COUNT().



Можно включить подсветку кода: <code><pre lang="">...</pre></code>
Разрешены некоторые HTML теги

или используйте trackback.