Різниця між getSize () та count () у колекції


81

Я багато разів чув, що вони обоє однакові. Але я стикаюся з дивною проблемою: у колекції продуктів модуля 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 () приймає старий рахунок. Має сенс?

Відповіді:


83

Більшість (якщо не всі) колекції поширюються 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()проблему, яка, у свою чергу, дозволила спеціальним та новим запитам баз даних знаходити продукти, виконувати умови "якщо" та належним чином рендерінг.


0

Коли до продуктів count($collection)був інший, ніж у $collection->getSize()мене reindex, то все працювало нормально.


-1

Існує головна відмінність для getSize () колекція продуктів не завантажується. Для count () він завантажить всю колекцію продуктів. Тому для великого каталогу не доцільно використовувати функцію підрахунку в будь-якій колекції.


Вже сказано в дописі Маріуса ...
sv3n
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.