我在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
对项目的调用吗?
答案 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()
实现了IteratorAggregate
和Countable
接口。他们的实施点是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());