Magento尝试在前端的事件观察器中保存产品时失败?


15

我有一个绑定到事件观察器的函数

要求之一是,当它遍历订单项数据时,如果某个产品属性为空,则发出请求以通过单独的模型获取特定数据(正常工作)。

问题代码基本上可以归结为

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();
}

但是Magento抛出了一个例外

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}

为什么我可以在magento观察器之外的第三方脚本中使用相同的代码,但是当我尝试在该观察器中运行它时,它失败并显示该随机错误消息?


此错误是非数组解析为的典型错误foreach。堆栈跟踪显示向您调度了一个事件,并且观察者有故障。您确定$order->getAllItems()要调音array()吗?使用:Zend_Debug::dump($order->getAllItems());。但是,可能是另一个观察者的代码错误吗?

问题出在Magento核心代码,而不是我的代码片段位于顶部。
Zxurian

Answers:


33

问题是,不允许您从前端保存产品。

这是通过以下事实完成的:在前端加载产品时,该origData属性未填充:

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

    return $this;
}

因此,当您尝试保存产品时,会出现您描述的错误。

您可以通过将当前商店更改为admin来解决此问题,例如使用@magboy中的代码:

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

更好地使用 Mage_Core_Model_App_Emulation

我首选的解决方案是扩展Mage_Catalog_Model_Product和替换setOrigData方法

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

不是在这里谈论重写!仅在此一个地方使用模型以启用保存。这样,您就可以在其他地方激活安全功能。


7

尝试添加以下代码行:

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

我不确定为什么现在必须在当前版本的Magento中执行此操作。也许其他人可以解释?


将currentstore设置为Admin并保存产品后,是否必须将其设置回原始值?
朱塞佩

1
@Giuseppe这取决于您稍后对请求的处理方式;如果您这样做,它会更清洁,并且可以减少问题的发生
simonthesorcerer 2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.