Magento: Load single product attribute vs. load entire product

Tweet about this on TwitterShare on LinkedInShare on Google+Share on FacebookEmail this to someone

Let’s assume that as developer you are in following situation: You know a product id and you have to fetch single attribute value of a product which id you already know. For example let’s try to get color attribute of Magento product.

Question: How would you do it? Are you going to load the product or you would look for more efficient solutions in order to fetch only the attribute you are looking for?

Magento allows us to fetch product attribute in many ways and depending on the context we could choose one. I am definitely against loading entire product in case there are much more efficient solutions and the goal is to fetch single product attribute (not all product attributes).

I think that people choose the easy way because:

  • People read the first answer (which sometimes is not the most efficient) in StackOverflow but don’t check other answers.
  • There is a lack of Magento documentation.
  • Missing out of the box way how to accomplish the task.
  • There are many examples in Internet but they are not descriptive enough to explain what happens on background and how efficient they are.


As first example, I would like to start with one of the efficient ways because I know many people would copy / paste this solution in their project, stop reading and continue with their daily work.

Load single product attribute:

Me and my colleague Attila Fabrik work on a legacy project and we noticed that in many places a product is loaded because a single attribute should be displayed. We registered this as serious problem because for example this code was used in block that was displayed on all pages. Each page refresh was leading to many product loads. This was serious red flag because we had high traffic Magento shop and every millisecond mattered.

We developed helper function that was wrapping all needed abstraction in order to fetch single product attribute value:

/**
 * @param int $productId
 * @param string $attributeCode
 * @param int|null $storeId
 * @return mixed
 */
public function fetchProductAttributeBy_ProductId_AttributeCode_StoreId($productId, $attributeCode, $storeId = null) {
    if (null === $storeId) {
        $storeId = Mage::app()->getStore()->getId();
    }

    $attribute = Mage::getModel('catalog/product')->getResource()->getAttribute($attributeCode);

    $attributeValue = Mage::getModel('catalog/product')
        ->getResource()
        ->getAttributeRawValue($productId, $attributeCode, $storeId);

    if ($attribute->usesSource()) {
        $attributeValue = $attribute->getSource()->getOptionText($attributeValue);
    }

    return $attributeValue;
}

The Store Id is optional parameter because we usually want to fetch product attribute from current store. I gave this long function name (fetchProductAttributeBy_ProductId_AttributeCode_StoreId) just to make it more descriptive. Feel free to give more suitable name in your projects. In some cases I would prefer to wrap this function in more meaningful named function because I would like to make my code more readable for teammates and fronted developers.

For example getColor():

public function getColor($productId) {
	$this-> fetchProductAttributeBy_ProductId_AttributeCode_StoreId($productId, ‘color’);
}

Generated SQL queries during fetching single attribute value:

Entire Product load:

Basically it looks strange to load entire product because you need a product attribute but many people do it.

This is what loading entire product will cause to your system:

  • a lot of not needed data could be loaded (other attributes, stock data, media gallery, prices and etc.)
  • increased execution time
  • more memory used compared to fetching single attribute approach
  • complex SQL query with couple of JOINs
  • not clean code (what was the exact purpose of loading the product if you pass it in a .phtml file and you just echo single attribute)
  • many events (after load, bore load) fired but may not need them when you need just a single attribute

If you are fine for what is listed above then you could try the following code snippet:

$_product = Mage::getModel('catalog/product')->load($id);
echo $_product->getAttributeText('color');

Generated SQL queries during product load:

“Benchmark”:

I wanted to see some numbers because I wanted check what is the difference between both methods described above. I didn’t use big numbers because for me was enough to see the difference when I tested with 10 products. For the tests I used Vagrant box with Magento CE 1.9.1.0 and sample product data.

Results of fetching single attribute (color) of 10 products:

  • Used memory: 2.49 MB
  • 42 ms in computations
  • 71 ms in system calls

Results of loading 10 products and getting color:

  • Used memory: 9.01 MB
  • 154 ms in computations
  • 342 ms in system calls

Conclusion:

I think that developers should be aware what are implications of their code and if they know better way then do tasks in better way. Of course everything is relative and it depends what is developer’s expertise in order to get nice and well performing code and successful project. The best thing that could happen is developers to get interested in Magento good practices and be aware that performance and simplicity matter in long term.

Your thoughts?

Tweet about this on TwitterShare on LinkedInShare on Google+Share on FacebookEmail this to someone

Tsvetan Stoychev

Tsvetan aka. Cecko is the founder of Cecko's Lab. He is Magento addicted since Magento CE 1.2.1.2 and has worked on over 30 Magento projects. At the moment he is in charge to take care about the money flow of the company, to keep constant communication with the clients and to keep the people in the office busy.

More Posts

Follow Me:
TwitterLinkedIn