0

I have a custom attribute for product called warehouse of type drop down.

In order to load the Sku => Warehouse (get assigned value for each product) updates between dates via models; I do the following:

// Load warehouse attribute options
$warehouse_options = array();
$options = array();
$attribute = Mage::getSingleton('eav/config')
    ->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'warehouse');
if ($attribute->usesSource()) {
    $options = $attribute->getSource()->getAllOptions(false);
}
$attribute = null;
foreach ($options as $option) {
    $warehouse_options[$option['value']] = $option['label'];
}
$options = null;

// Load all products updated since last sync
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToFilter('updated_at', array(
    'from' => $datetime_from,
    'to' => $datetime_to,
    'date' => true
));

// Init results
$results = array(
    'ServerDateTime' => $datetime_now,
    'Mapping' => array()
);

// Build results
foreach ($collection as $p) {
    $product = Mage::getModel('catalog/product')->load($p->getId());
    $results['Mapping'][] = array(
        'Sku' => $product->getSku(),
        'Warehouse' => isset($warehouse_options[$product->getWarehouse()]) ? $warehouse_options[$product->getWarehouse()] : ''
    );
    $product = null;
}
$collection = null;

This works, but quite slow as each product is getting loaded, so if I had 3000 products, thats 3000+ queries.

Is there a way to optimise this so I can load the desired data with minimal amount of query & processing?


I have tried to use just the collection like this using addAttributeToSelect:

$collection->addAttributeToSelect('sku', 'warehouse');

However, the returned $collection->getData() does not contain the field warehouse. Here's an example response array:

Array
(
    [0] => Array
        (
            [status] => 1
            [entity_id] => 4
            [type_id] => simple
            [attribute_set_id] => 4
            [updated_at] => 2015-07-07 15:35:35
            [sku] => C13S041061
        )
Latheesan
  • 23,247
  • 32
  • 107
  • 201

1 Answers1

1

When you call $collection->addAttributeToSelect('sku', 'warehouse');, you should be passing an array of all the details you want, not as separate function paramaters.

(Take a look at Mage_Catalog_Model_Resource_Product_Collection::addAttributeToSelect($attribute, $joinType = false)

So, your call should be:

$collection->addAttributeToSelect(array('sku', 'warehouse'));

In fact, you should be able to call:

$collection->addAttributeToSelect('warehouse');

as SKU should be a default value you get whether you specify it or not.

This will allow you to lose the additional Model call within your loop (which will really be killing your speed). With regard to the best way to go from here, my personal favourite is paged collections. Take a look here: http://www.douglasradburn.co.uk/dealing-with-large-collections-in-magento/

Essentially, something like this (example orders collection):

$ordersCollection = Mage::getModel('sales/order')->getCollection();
$ordersCollection->setPageSize(100);

$pages = $ordersCollection->getLastPageNumber();
$currentPage = 1;

do {
    $ordersCollection->setCurPage($currentPage);
    $ordersCollection->load();

    foreach ($ordersCollection as $_order) {
        // process
    }

    $currentPage++;
    // clear collection (if not done, the same page will be loaded each loop) - will also free memory
    $ordersCollection->clear();
} while ($currentPage < = $pages);
Douglas Radburn
  • 808
  • 4
  • 14