Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento product load - difference between loadByAttribute and load methods

Tags:

magento

today I'm fighting with Magento again :) and I found a difference between

$product = Mage::getModel('catalog/product')->loadByAttribute('sku', $product_sku);

and

$product = Mage::getModel('catalog/product')->load($product_id);

Can anyone exaplain me a difference between these two approaches? I found that when I'm loading a product by sku then when I 'try to re-save it with changed data then I get error exception 'Varien_Exception' with message 'Invalid method Varien_Object::save in app\code\core\Mage\CatalogInventory\Model\Observer.php(153): Varien_Object->__call('save', Array) that's true because once you try to load by sku then another observer sets product's stock item as Varien_Object, that looks like pitfall or I just dont understand it enough, but

I do daily Magento development from its beginnig so I know a lot about system and this is new for me. Thanks in advance, Jaro.

like image 283
Jaro Avatar asked Jun 07 '12 09:06

Jaro


2 Answers

Interesting. While both methods will net you a single product model instance with fully loaded EAV data (provided the third parameter of loadByAttribute() is not passed or is *), the observers which add stock-related data are different for products vs. product collections, yet both stock information objects are added to the product data key "stock_item". It's debatable, but this feels like a bug. I would think that Mage_CatalogInventory_Model_Observer::saveInventoryData() or Mage_CatalogInventory_Model_Observer::_prepareItemForSave() would handle this.

You could resolve this issue by setting the product stock item fully on your product instance using the stock_item object.

like image 150
benmarks Avatar answered Nov 08 '22 16:11

benmarks


loadByAttribute is a serious misnomer in my opinion because it doesn't actually trigger a load(); rather it uses getResourceCollection():

public function loadByAttribute($attribute, $value, $additionalAttributes = '*')
{
    $collection = $this->getResourceCollection()
        ->addAttributeToSelect($additionalAttributes)
        ->addAttributeToFilter($attribute, $value)
        ->setPage(1,1);

Because it doesn't trigger the observer events associated with load() it means the resulting product object doesn't include the full set of product data you might want. In my case I needed the "description" attribute and it wasn't included.

There are several ways to resolve this:

  • Use a different method to load by SKU:

      $product = Mage::getModel("catalog/product");
      $product->load($product->getIdBySku("whatever"));
    
  • Force the desired attribute data to be included in the default product resource data by visiting Magento Admin > Catalog > Attributes > Edit attribute > "Used in Product Listing" = "Yes" and then reindexing. You should then be able to use the attribute data (in the frontend, at least) using loadByAttribute().

See also https://magento.stackexchange.com/a/197286/18855

like image 37
WackGet Avatar answered Nov 08 '22 16:11

WackGet