删除项目后,Magento Varien_Data_Collection返回错误的大小

时间:2013-12-11 19:13:03

标签: magento-1.4

我在Magento 1.4上运行,但也在1.7中验证了这个问题。

使用Varien_Data_Collection的实例可以使用Varien_Data_Collection::removeItemByKey。在我的情况下,我正在从集合中删除项目,然后尝试获取该集合的更新大小,如下所示:

$body=$this->getTable()->getBody();

echo $body->getHeight(); // Outputs 25

$body->deleteRow(1);

echo $body->getHeight(); // Still outputs 25

...

My_Model_Body_Class extends Mage_Core_Model_Abstract {

  /* @var $_rows Varien_Data_Collection */
  protected $_rows;

  public function deleteRow($index) {
    $this->_rows->removeItemByKey($index);

    return $this;
  }

  public function getHeight() {
    return $this->_rows->getSize();
  }

}

...

代码仅限于简洁。

因此,如果您调用我的deleteRow方法,该项目实际上将从集合中删除,但后续调用以获取该集合的大小将始终返回原始计数。 因此,如果我在集合中有25个项目,并删除1,那么对该集合的getSize的调用将返回25

我在Varien_Data_Collection::getSize

中追溯到父类
/**
 * Retrieve collection all items count
 *
 * @return int
 */
public function getSize()
{
    $this->load();
    if (is_null($this->_totalRecords)) {
        $this->_totalRecords = count($this->getItems());
    }
    return intval($this->_totalRecords);
}

我们看到计数取决于_totalRecords属性的NULL状态。所以它看起来像核心代码中的一个错误。我读得对吗?我应该只依赖于count对项目的调用吗?

1 个答案:

答案 0 :(得分:6)

  

我们看到计数取决于_totalRecords的NULL状态   属性。所以它看起来像核心代码中的一个错误。我读这个吗   正确?

是否将所述行为解释为错误或特征,取决于旁观者的眼睛。

这个行为不是1.4具体的,顺便说一下;它的工作方式与当前的CE版本(1.8.1)相同。

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

大多数人肯定希望名为getSize()的方法始终返回当前大小,因此他们可能会将其称为错误。

但是如果你仔细看看Varien_Data_Collection类,你会注意到,getSize()并不是唯一看起来有点像......“怪异的”。

例如,使用addItem()removeItemByKey()方法。

_totalRecords使用getSize()时,为什么不增加/减少Varien_Data_Collection属性?

延迟加载

这些“怪异”行为的原因是,Varien_Data_Collection基本上是为Lazy Loading模式的使用而设计的。这意味着,它允许延迟加载集合,直到真正需要数据。

为实现此目的,getIterator()实现了IteratorAggregateCountable接口。他们的实施点是count()public function getIterator() { $this->load(); return new ArrayIterator($this->_items); } public function count() { $this->load(); return count($this->_items); } 方法:

load()

如您所见,这两种方法都首先调用foreach

结果是,无论何时在集合上使用count()或PHP函数load(),都会自动调用Varien_Data_Collection方法。

现在,对于默认load(),调用load()时不会发生任何特殊情况,因为loadData()仅调用loadData()$this仅返回{{ 1}}。

但是当涉及到其使用频繁的子类Varien_Data_Collection_Db时,对load()的调用将导致加载集合并将_totalRecords设置为SQL count加载记录。

出于性能原因,该集合通常仅加载一次(如果尚未加载)。

所以你看,根据你使用Varien_Data_Collection的上下文,它完全有道理,为什么getSize()会这样做。

  

我应该只依赖于count对项目的调用吗?

如果您的收藏不受复杂或缓慢的I / O限制,我会说:

您可以简单地使用:

$n = count($this->_rows->getItems());

甚至这样:

$n = count($this->_rows->getIterator());