Collection – addAttributeToSelect Not Working with core/resource_iterator

collection;

public function run()
{
    $products = Mage::getModel('catalog/product')
            ->getCollection()
            ->addFinalPrice()
            ->addAttributeToSelect('name')

    Mage::getSingleton('core/resource_iterator')
            ->walk($products->getSelect()->limit(10), array(array($this, 'getLine')));

}

public function getLine($args)
{
    var_dump($args['row']);
}

In my getLine() method I get no name but addFinalPrice() works:

array(16) {
  ["entity_id"]=>
  string(2) "61"
  ["entity_type_id"]=>
  string(1) "4"
  ["attribute_set_id"]=>
  string(2) "10"
  ["type_id"]=>
  string(6) "simple"
  ["sku"]=>
  string(15) "50-F01010001-03"
  ["has_options"]=>
  string(1) "0"
  ["required_options"]=>
  string(1) "0"
  ["created_at"]=>
  string(19) "2011-07-05 18:30:48"
  ["updated_at"]=>
  string(19) "2014-09-04 07:34:21"
  ["indexed_price"]=>
  string(7) "14.5000"
  ["price"]=>
  string(7) "14.5000"
  ["final_price"]=>
  string(7) "14.5000"
  ["minimal_price"]=>
  string(7) "14.5000"
  ["min_price"]=>
  string(7) "14.5000"
  ["max_price"]=>
  string(7) "14.5000"
  ["tier_price"]=>
  NULL
}

Same problem with image, price and every other attribute.

Best Answer

Unfortunately the core/iterator resource model does not work well with EAV models, because it directly works with the query and does not use any of the collection specific features.

This is what usually happens when loading an EAV collection (I'll simplify a bit):

  • select basic data from the entity table (this is what $collection->getSelect() does
  • load the attributes from the value tables with an additional query and add this data to each loaded model

This all happens in the load() method (see Mage_Eav_Model_Entity_Collection_Abstract::_loadAttributes() if you want to see the implementation details)

Since the reason for using the resource iterator is usually that you don't want to load all data at once, you cannot use this feature in a reasonable way.

I tried to build a single query with joins instead, but soon ran into the problem that MySQL "only" allows 63 joins at a time. If you only need a few attributes, it might work for you, though.

Otherwise your best bet is to load and process the collection in chunks like this:

$ids = Mage::getModel('catalog/product')
    ->getCollection()
    ->getAllIds();

$page = 1;
do {
    $collection = Mage::getModel('catalog/product')
        ->getCollection()
        ->addIdFilter($ids)
        ->setPageSize(100)
        ->setPage($page);
    $results = $collection->load();
    // do stuff ...
    $page++;
} while ($results->count());