Getting the first item in a collection without breaking a pager

I posed a question about this before, but now I have more information, and I thought it was better to post a new one rather than modify it (sorry if this is not the correct protocol). You can find my original question here .

Anyway, the original problem was that I wanted to check the first item in the collection inside the List.php class right after setting the collection so that I could clear the category and use it to view reviews. All this was based on a user module, so there were a lot of variables. Since then, I tried it in the default Magento sample repository and added only ONE to app/code/core/Mage/catalog/Block/Product/List.php to break the pager. Here are the details. If you have any idea why this is happening, let me know when I'm stuck.

First open app/code/core/Mage/catalog/Block/Product/List.php and find the _getProductCollection function. At the end of the if (is_null...) block add $_foo123 = $this->_productCollection->getFirstItem(); so that 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 just go to any list of products that uses this class (for example, a category view) and you will see what I mean. No matter what you select in the Show XX section of the page on the toolbar, it always displays all the items in the list. If you comment out the line $_foo123... , it works fine.

What gives?

PS I know that I should not edit the main files ... this is just an example :)

+4
source share
1 answer

The reason is that when you call getFirstItem() (or just about any other search method) in the collection into which the collection is loaded. Any subsequent operation ignores the database and uses only the loaded data, the filters do not affect it, because they are only SQL, and not for pagination and selected columns. A workaround is to use the second collection based on the first.

 $secondCollection = clone $firstCollection; $secondCollection->clear(); $_foo123 = $secondCollection->getFirstItem(); 

The clear() method unloads data for this collection, causing it to access the database again the next time.

+14
source

All Articles