Magento échoue lors de la tentative de sauvegarde du produit dans l'observateur d'événements sur le frontend?


15

J'ai une fonction liée à un observateur d'événement

L'une des exigences est que lorsqu'il parcourt les données de l'article de commande, si un certain attribut de produit est vide, il émet une demande pour obtenir des données spécifiques via un modèle distinct (fonctionne correctement).

le code du problème se résume essentiellement à cette

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

mais Magento lance une exception de

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}

Pourquoi serais-je capable d'utiliser du code identique dans un script tiers en dehors de l'observateur magento, mais quand j'essaye de l'exécuter à l'intérieur de cet observateur, il échoue avec ce message d'erreur aléatoire?


Cette erreur est typique d'un non-tableau analysé foreach. La trace de pile vous montre qu'un événement est distribué et que l'observateur est défectueux. Êtes-vous sûr de $order->getAllItems()réaccorder un array()? utiliser: Zend_Debug::dump($order->getAllItems());. Cependant, ce pourrait être un autre observateur avec un mauvais code?
ash

le problème est avec le code de base de Magento, pas avec mon extrait de code en haut.
Zxurian

Réponses:


33

Le problème est que vous n'êtes pas autorisé à enregistrer des produits depuis le frontend.

Cela se fait par le fait que lorsque vous chargez un produit en frontend, la origDatapropriété n'est pas remplie:

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

    return $this;
}

Ainsi, lorsque vous essayez d'enregistrer le produit, l'erreur que vous décrivez est déclenchée.

Vous pouvez résoudre ce problème soit lorsque vous changez le magasin actuel en admin, par exemple avec le code de @magboy:

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

mieux utiliser Mage_Core_Model_App_Emulation

Et ma solution préférée est d'étendre Mage_Catalog_Model_Productet de remplacer la setOrigDataméthode

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

Je ne parle pas d'une réécriture ici! N'utilisez votre modèle que sur ce même emplacement pour activer l'enregistrement. Ensuite, la fonction de sécurité est toujours active partout ailleurs.


7

Essayez d'ajouter cette ligne de code:

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

Je ne sais pas pourquoi vous devez le faire maintenant dans la version actuelle de Magento. Peut-être que quelqu'un d'autre peut expliquer?


après avoir défini le magasin actuel sur Admin et enregistré le produit, dois-je le restaurer à sa valeur d'origine?
Giuseppe

1
@Giuseppe Cela dépend de ce que vous faites plus tard avec la demande; il est plus propre et entraînera moins de problèmes si vous le faites
simonthesorcerer
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.