Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$product->save(); causing an error - when changing product qty

Tags:

php

magento

I am creating a custom module.

I am testing the ability to update a products quantity.

I have created a bare bones magento module and began testing with code inside indexController.php here is my code:

public function indexAction() {

    //Just grabbing sku# 62701 for testing...
    $tempProduct = Mage::getModel('catalog/product')->loadByAttribute('sku', 62701 );

    $stockData['qty'] = 300;
    $tempProduct->setStockData($stockData);

    $tempProduct->save(); 

}

By having the last line in there i get the error.

From the error log:

a:5:{i:0;s:46:"Invalid method Varien_Object::save(Array ( )

Followed by the stack trace...

Any help is appreciated, thank you.

like image 337
shnozolla Avatar asked Sep 24 '12 20:09

shnozolla


4 Answers

I had to look into this issue and found the problem. The whole stock data/item interface is a bit tricky.

Problem

Mage_Catalog_Model_Abstract->loadByAttribute uses collection-loading on collection catalog/product_collection with a limit of 1.

Stock items of products in that collection are loaded via the event observer Mage_CatalogInventory_Model_Observer->addStockStatusToCollection which listens to event catalog_product_collection_load_after. addStockStatusToCollection loads stock items of products only if flag require_stock_items is set true.

In case of Mage_Catalog_Model_Abstract->loadByAttribute this flag isn't set so we end up with $product->_data['stock_item'] being of type Varien_Object (see Mage_CatalogInventory_Model_Stock_Status lines 488-491).

This causes error

Invalid method Varien_Object::save...

on $product->save.

I recommend solution 1 if you save the product anyway and want the stock update to happen in the same transaction. Solution 2 only sets stock data so it avoids calling expensive $product->save.

Solution 1

Use an additional load on the product: this loads $product->_data['stock_item'] properly.

Mage::getModel('catalog/product')->loadByAttribute('sku', 62701 );
$tempProduct->load($tempProduct->getId());

This is an additonal read transaction on the database which slows things down.

Solution 2

As in other answers suggested use the class Mage_CatalogInventory_Model_Stock_Item directly. But you have reference the product correctly via call to setProduct to have working code both for new and existing stock items.

$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product->getId());
$stockItem->setProduct($product)
    ->setData('stock_id', Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID)
    ->setData('qty', 1)
    ->setData('is_in_stock', 1)
    ->setData('manage_stock', 1)
    ->setData('use_config_manage_stock', 0)
    ->setData('use_config_backorders', 0)
    ->setData('backorders', 0)
    ->setData('use_config_max_sale_qty', 0)
    ->setData('max_sale_qty', 1)                
    ->save();
like image 167
fheyer Avatar answered Nov 15 '22 07:11

fheyer


I found a way to save data that seemed to work in my scenario (not sure why it worked) here: https://stackoverflow.com/a/7608195/1110880

The code that made it work was the following:

    $productId = $tempProduct->getId();
    $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);
    $stockItem->setData('qty', $qty);

    $stockItem->save();

I hope this helps someone.

like image 28
shnozolla Avatar answered Nov 15 '22 08:11

shnozolla


I can see two potential problems.

  1. Are you sure that loadByAttribute('sku', 62701 ) can only return one item? (That error has shown up when people have tried to update more than one thing at once.)
  2. $stockData is not defined. At a minimum it would be safer to define it.

It looks like you're missing something like this:

$stockData = $tempProduct->getStockData();
like image 32
cwallenpoole Avatar answered Nov 15 '22 08:11

cwallenpoole


I'm probably doing something wrong, but I had the same problem and this helped:

$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product->getId());
$stockItem->setProductId($product->getId());
$stockItem->setStockId(Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID);
like image 41
trias Avatar answered Nov 15 '22 06:11

trias