集合上的getSize()和count()之间的区别


81

我已经多次听到他们都是一样的。但是我面临一个奇怪的问题,在CatalogSearch模块的产品集合中,count()返回正确的产品计数,而getSize()返回零。

所以,基本上这就是我得到的:

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

但是我希望getSize()具有正确的计数,因为它决定是否在搜索页面中显示分页和产品。我仅在集合中使用“内部联接”,“左联接”和“位置”条件以更具体。

有什么想法为什么我遇到这个奇怪的问题?

谢谢

更新:

我之前的问题,如何在Magento中克隆收藏?我想对一个集合执行两个不同的操作。第一个集合显示正确的getSize(),但是如果getSize()为零,则删除WHERE子句并给出新的WHERE条件。在这之后,我得到了我期望的正确的原始SQL,并且在MySQL中运行它也提供了一组正确的记录,但是集合上的只有getSize()给出了零计数。

所以基本上我可能需要重新加载集合,因为getSize()占用了旧的计数。说得通?

Answers:


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()原始集合之前尝试克隆该集合。也许会起作用。
马里斯(Marius)

您还可以执行以下操作来获得“重置”计数:$sql = $collection->getSelectCountSql(); return $collection->getConnection()->fetchOne($sql);
koosa

14

小心。这是正确的,但方法已Varien_Data_Collection_Db如Marius所述覆盖

看看

// \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

更新了条目
Fabian Blechschmidt

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()问题,从而使Special和New数据库请求可以找到产品,满足“ if”条件并正确渲染。


0

count($collection)$collection->getSize()reindex的产品有所不同时,一切都很好。


-1

对于getSize(),主要区别在于未加载产品集合。对于count(),它将加载整个产品集合。因此,对于大型目录,建议不要在任何集合中使用count函数。


已经在Marius帖子中说过
sv3n,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.