Using Magento's resource iterator model on a product collection
I recently found the following article regarding using Magento's resource iterator model when calling large product collections, to save on resources - http://www.fontis.com.au/blog/magento/loading-large-collections. However, I'm finding it hard to figure out exactly how to get it to output the exact same data.
So, suppose I'm using the following the get a full product collection and output the sku's:
$productCollection = Mage::getModel('catalog/product')->getCollection();
foreach($productCollection as $product){
echo $product->getSku().',';
}
Using the profiler, I see this is using 1,154,480 bytes to process.
Now using the resource iterator model like so:
function productCallback($args)
{
$product = Mage::getModel('catalog/product');
$product->setData($args['row']);
echo $product->getSku().',';
}
$_productCollection = Mage::getModel('catalog/product')->getCollection();;
$_productCollection = Mage::getSingleton('core/resource_iterator')->walk($_productCollection->getSelect(), array('productCallback'));
This uses 199,912 bytes. So quite a difference to get the same thing, just a basic list of sku's.
But my problem is, for example, if I wanted to make a nicely styled list of products, and get their images, urls etc, I would previously use a foreach loop on $productCollection, as in the first example:
foreach($_productCollection as $product){
echo $product->getSku().',';
};
But this no longer works. It looks like when it goes through th开发者_如何学编程e callback, that acts the same as a foreach loop, running each product through in turn.
So, how do I get my collection back in the same format as before, so it again works in a foreach loop? Do I need to add the products to an array? If so, how do I do that?
I think you might be missing the point. A resource iterator is nice when you don't need the full object-orientated approach nor an array of records and can work with raw values from the database.
For outputting things like images and prices you need instances of product objects that have the functions for working out image thumbnails, or how discounts affect the price. Also when a product object loads it fires various events so other modules get to make their modifications too, that is part of what makes Magento so extensible. If you're worried about memory use or execution time then cache the product list block and don't change anything else.
@clockworkgeek - You are correct. To add to this,
$visibility = array(
Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
);
$_productCollection = Mage::getResourceModel('reports/product_collection')
->addAttributeToSelect('*')
->addOrderedQty()
->addAttributeToFilter('visibility', $visibility)
->setOrder('ordered_qty', 'desc');
The question was made a while ago but I'd like to add it is possible to load the product in callback function and get any attribute you need and store it in an object's protected member array via a public method.
For example you may have a model like
class Company_Module_Model_Indexer_Entity_Product
public function addToData($key, $data)
{
$this->_data[$key] = $data;
}
then within a method of this class you can have:
Mage::getSingleton('core/resource_iterator')->walk($products->getSelect(), array(
function ($args) {
$rowProduct = Mage::getModel('catalog/product')->setData($args['row']);
$indexKey = $rowProduct->getId();
$product = Mage::getModel('catalog/product')->load($rowProduct->getId());
$args['invoker']->addToData($indexKey, [YOUR_DATA]);
}
), array('invoker' => $this));
精彩评论