Magento Catch-22 Collection

I really don't understand how Magento collections work, so hopefully this is a simple question ...

As the old saying goes, you cannot observe an experiment without changing it. This is similar to the Magento collection. I have a Featured Products module that I wrote that works quite well. We recently added customer reviews to our store. When viewing a category page, it shows a random overview of products in this category. This also works great. I added a review block to the Featured Products page, which was easy to do, but since these products aren't categorized, they just pull out a random, usually unrelated view. To fix this, I changed my getProductCollection function in my Featured module and added the following to the end after creating / saving the collection:

$_product = $this->_productCollection->getFirstItem(); $_catIDs = $_product->getCategoryIds(); if(count($_catIDs) > 0) { $_cat = Mage::getModel('catalog/category')->load($_catIDs[0]); Mage::register('current_category', $_cat); } 

Unfortunately, the simple act of finding the first item in a collection breaks the pager on the toolbar. Regardless of which of the parameters of the search call I choose, it always shows all the elements when the above code is in place. If I comment on this section, it works great.

So my question is this: how can I get any information about the products in the collection without somehow changing the collection or breaking the paging?

Adding my code to help explain the problem more:

 class VPS_Featured_Block_List extends Amasty_Sorting_Block_Catalog_Product_List//Mage_Catalog_Block_Product_List { protected function _getProductCollection() { if (is_null($this->_productCollection)) { $_attributeNames = 'featured'; if($this->getAttributeName() != '') $_attributeNames = $this->getAttributeName(); $_attrArray = explode(',', $_attributeNames); $this->_productCollection = Mage::getModel('catalog/product')->getCollection(); $this->_productCollection->addAttributeToSelect('*'); $_filters = array(); foreach($_attrArray as $_attr) $_filters[] = array('attribute' => $_attr, 'eq' => true); $this->_productCollection->addFieldToFilter($_filters); //$this->_productCollection->addFieldToFilter(array(array('attribute' => $_attr, 'eq' => true),)); Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($this->_productCollection); Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($this->_productCollection); Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($this->_productCollection); //Get category of first product in collection (used for featured review) $_catIDs = array(); $_product = $this->_productCollection->getFirstItem(); $_catIDs = $_product->getCategoryIds(); if(count($_catIDs) > 0) { $_cat = Mage::getModel('catalog/category')->load($_catIDs[0]); Mage::register('current_category', $_cat); } } return $this->_productCollection; } } 
+2
source share
2 answers

Thanks to @clockworkgeek for this answer that he posted in my follow-up question :

The reason is that when you call getFirstItem () (or almost 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, forcing it to access the database again next time

+4
source

It is difficult to say what happens without additional context (magento version, what class you are, etc.) BUT, what I think (60% certainty) that this is happening, you get a link to the product collection before the filters are added. Magento collections are lazy, which means that database queries do not run until you explicitly name the load or attempt to access the item. My hunch (again, the assumption) is that when accessing the item above, the collection loads (without a filter). Then other parts of the system add a filter , but they are ignored because the collection is already loaded .

The answer to your larger question is not possible without additional context.

+1
source

All Articles