Разница между getSize () и count () в коллекции

82

Я много раз слышал, что они оба одинаковы. Но я столкнулся со странной проблемой: в коллекции продуктов модуля CatalogSearch count () возвращает правильное количество продуктов, а getSize () возвращает ноль.

Итак, в основном это то, что я получаю:

$collection->count(); //correct count
$collection->getSize(); //0

Но я хочу, чтобы getSize () имел правильное количество, так как он решает, показывать нумерацию страниц и продукты на странице поиска или нет. Я использую условия Inner Join, Left Join и Where только в коллекции, чтобы быть более конкретными.

Есть идеи, почему я получаю эту странную проблему?

Спасибо

ОБНОВИТЬ:

Мой предыдущий вопрос: Как клонировать коллекцию в Magento? Я хотел выполнить две разные операции над одной коллекцией. Первая коллекция показывает правильный getSize (), но затем, если getSize () равен нулю, я удалил предложение WHERE и дал новое условие WHERE. После этого я получаю правильный исходный SQL, что и ожидал, и запуск его в MySQL также дает правильный набор записей, но только getSize () в коллекции дает нулевое число.

Так что в основном мне может понадобиться перезагрузить коллекцию, так как getSize () принимает старый счет. Имеет смысл?

MagExt
источник

Ответы:

84

Большинство (если не все) коллекции расширяются Varien_Data_Collection_Db. Вот 2 метода из этого класса

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        $sql = $this->getSelectCountSql();
        $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
    }
    return intval($this->_totalRecords);
} 

public function count() //inherited from Varien_Data_Collection
{
    $this->load();
    return count($this->_items);
}

Есть разница. Для getSize()коллекции не загружается. Ибо count()это так. Обычно модели коллекции используют тот же getSize()метод, что и выше, и только переопределяют getSelectCountSql().
При getSelectCountSql()этом лимит сбрасывается для того, чтобы получить общее количество записей, доступных для заданных фильтров ( whereвыписка). Посмотрите, как getSelectCountSql()работает

public function getSelectCountSql()
{
    $this->_renderFilters();
    $countSelect = clone $this->getSelect();
    $countSelect->reset(Zend_Db_Select::ORDER);
    $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
    $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
    $countSelect->reset(Zend_Db_Select::COLUMNS);
    $countSelect->columns('COUNT(*)');
    return $countSelect;
} 
Мариус
источник
3
Большой! Итак, каким должен быть мой следующий шаг, чтобы перезагрузить коллекцию, чтобы она стала правильной getSize()? Спасибо!
MagExt
Я, честно говоря, не знаю, почему вы получаете этот результат. В CatalogSearchмодуле нет ничего, что переопределяет getSize()или getSelectCountSql(). Он должен работать по умолчанию, если только вы не добавили какой-то пользовательский код. Можете ли вы опубликовать способ создания коллекции?
Мариус
обновил вопрос.
MagExt
3
Там нет способа сбросить _totalRecords. Вы можете попытаться клонировать коллекцию перед вызовом getSize()исходной коллекции. Может быть, это сработает.
Мариус
Вы также можете сделать что-то вроде этого, чтобы получить счетчик «сброса»:$sql = $collection->getSelectCountSql(); return $collection->getConnection()->fetchOne($sql);
koosa
14

Быть осторожен. Это правильно, но методы перезаписываются, Varien_Data_Collection_Dbкак описано Мариусом.

Просто взгляните на

// \Varien_Data_Collection::getSize
public function getSize()
{
    $this->load();
    if (is_null($this->_totalRecords)) {
        $this->_totalRecords = count($this->getItems());
    }
    return intval($this->_totalRecords);
}

// \Varien_Data_Collection::count
public function count()
{
    $this->load();
    return count($this->_items);
}

Так что на этом низком уровне должно быть то же самое. Оба метода загружают коллекцию и подсчитывают элементы.

ОБНОВИТЬ

О, я вижу проблему: getSize () кэширует _totalRecords, это означает, что он не пересчитывается. Проверьте, где _totalRecordsустановлен?

Фабиан Блехшмидт
источник
Да, я смотрел на это, но не могу понять, почему оба генерируют разные подсчеты для одной и той же коллекции? Любые идеи, как перезагрузить коллекцию или что-то, чтобы получить правильный счет getSize()?
MagExt
обновил запись
Фабиан Блехшмидт
1
getSize()не загружает коллекцию для записей, поступающих из базы данных. Нет, если вы не переопределите метод и не скажете ему загрузить коллекцию.
Мариус
_totalRecords защищен, поэтому не могу вызвать его в моем пользовательском файле с коллекцией. echo count($collection->load()->getItems());дает правильный счет, но я снова хочу getSize()работать.
MagExt
5

Этот ответ отображается в Google как "magento getSize неправильно" и подобные поиски, поэтому я хотел бы добавить возможный сценарий, который может быть полезен для кого-то

Когда в вашем запросе есть оператор группы, и вы делаете

SELECT COUNT(DISTINCT e.entity_id) ... GROUP BY ( at_id_art.value )

Mysql вернет счетчик для КАЖДОГО из групп, поэтому Varien_Data_Collection_Db :: getSize () вернет неправильный ответ, потому что эта функция выбирает первую строку:

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        $sql = $this->getSelectCountSql();
        $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
    }
    return intval($this->_totalRecords);
}

Когда он заселит

$this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);

Он выбирает первую строку и, следовательно, возвращает сумму первой группы как общий размер.

В итоге я придумал этот код для подсчета, основанный на уникальных значениях атрибутов в моем запросе.

$select = clone $collection->getSelect();
$group = $select->getPart(Zend_Db_Select::GROUP);
$select->reset(Zend_Db_Select::GROUP)->reset(Zend_Db_Select::COLUMNS)->columns("COUNT(DISTINCT {$group[0]})");
$totalCount = $collection->getConnection()->fetchOne($select);
подменыш
источник
2

На случай, если вы окажетесь здесь, попробуйте другое простое исправление:

System -> Index Management

и выберите их все (даже если они указывают «Зеленый, переиндексировать не нужно») и принудительно переиндексировать.

Это решило мою пустую getSize()проблему, которая, в свою очередь, позволила запросам в Специальной и Новой базе данных найти продукты, выполнить условия «если» и правильно отобразить.

BVRoc
источник
0

Когда count($collection)было иначе , чем $collection->getSize()я должен был reindexпродукты, то все работало нормально.

Zsolti
источник
-1

Есть главное отличие Для getSize () коллекция продуктов не загружена. Для count () он загрузит всю коллекцию продуктов. Поэтому для большого каталога не рекомендуется использовать функцию подсчета в любой коллекции.

Наян Барайя
источник
Уже сказано в посте Мариуса ...
sv3n