15

I have a function that is tied to an event observer

One of the requirements is that when it loops through the order item data, if a certain product attribute is empty it issues a request to get specific data through a separate model (working fine).

the problem code basically boils down to this

foreach ($order->getAllItems() as $key => $item) {
    /** @var Tantor_Catalog_Model_Product $productData */
    $productData = $item->getProduct();
    $_item = Mage::getModel('catalog/product')->load($productData->getId());
    $_item->setNetsuiteItemIid('foo');
    $_item->save();
}

however Magento is throwing an exception of

2014-03-05T21:14:14+00:00 ERR (3):
exception 'Exception' with message 'Warning: Invalid argument supplied for foreach()  in /var/www/html/app/code/core/Mage/Eav/Model/Entity/Abstract.php on line 1180' in /var/www/html/app/code/core/Mage/Core/functions.php:245
Stack trace:
#0 /var/www/html/app/code/core/Mage/Eav/Model/Entity/Abstract.php(1180): mageCoreErrorHandler(2, 'Invalid argumen...', '/var/www/html/a...', 1180, Array)
#1 /var/www/html/app/code/core/Mage/Eav/Model/Entity/Abstract.php(1123): Mage_Eav_Model_Entity_Abstract->_collectSaveData(Object(Tantor_Catalog_Model_Product))
#2 /var/www/html/app/code/core/Mage/Core/Model/Abstract.php(318): Mage_Eav_Model_Entity_Abstract->save(Object(Tantor_Catalog_Model_Product))
#3 /var/www/html/app/code/local/Tantor/Netsuite/Model/Observer.php(218): Mage_Core_Model_Abstract->save()
#4 /var/www/html/app/code/core/Mage/Core/Model/App.php(1338): Tantor_Netsuite_Model_Observer->saveOrder(Object(Varien_Event_Observer))
#5 /var/www/html/app/code/core/Mage/Core/Model/App.php(1317): Mage_Core_Model_App->_callObserverMethod(Object(Tantor_Netsuite_Model_Observer), 'saveOrder', Object(Varien_Event_Observer))
#6 /var/www/html/app/Mage.php(447): Mage_Core_Model_App->dispatchEvent('sales_order_pla...', Array)
#7 /var/www/html/app/code/core/Mage/Sales/Model/Order.php(1096): Mage::dispatchEvent('sales_order_pla...', Array)
#8 [internal function]: Mage_Sales_Model_Order->place()
#9 /var/www/html/app/code/core/Mage/Core/Model/Resource/Transaction.php(105): call_user_func(Array)
#10 /var/www/html/app/code/core/Mage/Core/Model/Resource/Transaction.php(159): Mage_Core_Model_Resource_Transaction->_runCallbacks()
#11 /var/www/html/app/code/core/Mage/Sales/Model/Service/Quote.php(189): Mage_Core_Model_Resource_Transaction->save()
#12 /var/www/html/app/code/core/Mage/Sales/Model/Service/Quote.php(249): Mage_Sales_Model_Service_Quote->submitOrder()
#13 /var/www/html/app/code/core/Mage/Checkout/Model/Type/Onepage.php(774): Mage_Sales_Model_Service_Quote->submitAll()
#14 /var/www/html/app/code/core/Mage/Checkout/controllers/OnepageController.php(511): Mage_Checkout_Model_Type_Onepage->saveOrder()
#15 /var/www/html/app/code/core/Mage/Core/Controller/Varien/Action.php(419): Mage_Checkout_OnepageController->saveOrderAction()
#16 /var/www/html/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(250): Mage_Core_Controller_Varien_Action->dispatch('saveOrder')
#17 /var/www/html/app/code/core/Mage/Core/Controller/Varien/Front.php(176): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
#18 /var/www/html/app/code/core/Mage/Core/Model/App.php(354): Mage_Core_Controller_Varien_Front->dispatch()
#19 /var/www/html/app/Mage.php(683): Mage_Core_Model_App->run(Array)
#20 /var/www/html/index.php(86): Mage::run('', 'store')
#21 {main}

Why would i be able to use identical code in a 3rd party script outside the magento observer just fine, but when I try to run it inside that observer, it fails with that random error message?

  • This error is typical of a non-array being parsed into foreach. The stack trace shows you an event is dispatched and the observer is faulty. Are you sure $order->getAllItems() is retuning an array()? use: Zend_Debug::dump($order->getAllItems());. However, it might be another observer with some bad code? – ash Mar 6 '14 at 17:17
  • the problem is with Magento core code, not with my snippet at the top. – Zxurian Mar 7 '14 at 18:45
33

The problem is, that you are not allowed to save products from the frontend.

This is done through the fact, that when you load a product in frontend, the origData property is not filled:

public function setOrigData($key=null, $data=null)
{
    if (Mage::app()->getStore()->isAdmin()) {
        return parent::setOrigData($key, $data);
    }

    return $this;
}

So when you try to save the product, the error you describe is raised.

You can solve this problem either when you change the current store to admin, e.g. with the code from @magboy:

Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

better using Mage_Core_Model_App_Emulation

And my prefered solution is to extend Mage_Catalog_Model_Product and replace the setOrigData method

public function setOrigData($key = null, $data = null)
{
    if (is_null($key)) {
        $this->_origData = $this->_data;
    } else {
        $this->_origData[$key] = $data;
    }
    return $this;
}

I'm NOT talking about a rewrite here! Only use your model on this one place to enable saving. Then you have the security-feature still active everywhere else.

7

Try adding this line of code:

Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

I'm not sure why you have to do this now in the current version of Magento. Maybe someone else can explain?

  • after I set the currentstore to Admin and saved the product, do I have to set it back to the original value ? – Giuseppe Mar 30 '16 at 16:49
  • 1
    @Giuseppe It depends what you are doing later on with the request; it's cleaner and will lead to less issues if you do it – simonthesorcerer Apr 13 '16 at 8:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.