I posted a question about this earlier, but I have more information now and I thought it best to post a new one rather than modify (sorry if that's not proper protocol). You can find my original question here.
Anyhow, the initial problem was that I wanted to inspect the first item in a collection inside the List.php class just after setting the collection so that I could scrape the category and use that to show reviews. This was all based off a custom module, so there were a lot of variables. I have since tried it on a default Magento sample store and only added ONE line to app/code/core/Mage/catalog/Block/Product/List.php
to break the pager. Here are the details. If you have any ideas why this is happening, please let me know as I'm stuck
First, open app/code/core/Mage/catalog/Block/Product/List.php
and locate the _getProductCollection
function. At the end of the if (is_null...)
block, add $_foo123 = $this->_productCollection->getFirstItem();
so you have a function that looks like this:
protected function _getProductCollection()
{
if (is_null($this->_productCollection)) {
$layer = $this->getLayer();
/* @var $layer Mage_Catalog_Model_Layer */
if ($this->getShowRootCategory()) {
$this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
}
// if this is a product view page
if (Mage::registry('product')) {
// get collection of categories this product is associated with
$categories = Mage::registry('product')->getCategoryCollection()
->setPage(1, 1)
->load();
// if the product is associated with any category
if ($categories->count()) {
// show products from this category
$this->setCategoryId(current($categories->getIterator()));
}
}
$origCategory = null;
if ($this->getCategoryId()) {
$category = Mage::getModel('catalog/category')->load($this->getCategoryId());
if ($category->getId()) {
$origCategory = $layer->getCurrentCategory();
$layer->setCurrentCategory($category);
}
}
$this->_productCollection = $layer->getProductCollection();
$this->prepareSortableFieldsByCategory($layer->getCurrentCategory());
if ($origCategory) {
$layer->setCurrentCategory($origCategory);
}
//THIS LINE BREAKS THE PAGER
$_foo123 = $this->_productCollection->getFirstItem();
}
return $this->_productCollection;
}
Now, simply go to any product list that uses that class (category view, for instance) and you'll see what I mean. No matter what you choose under Show XX per page in the toolbar, it will always show you all items in the list. If you comment out that $_foo123...
line, it works fine.
What gives??
P.S. I know I'm not supposed to edit core files...this is just an example :)
The reason is because when you call getFirstItem()
(or just about any other retrieval method) on a collection that collection is loaded. Any subsequent operation ignores the database and uses only the loaded data, filters have no effect because they are SQL only, ditto for pagination and selected columns. The workaround is to use a second collection based on the first.
$secondCollection = clone $firstCollection;
$secondCollection->clear();
$_foo123 = $secondCollection->getFirstItem();
The clear()
method unloads the data for that collection, forcing it to access the database again next time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With