¿Magento falla al intentar guardar el producto dentro del observador de eventos en la interfaz?

15

Tengo una función que está vinculada a un observador de eventos.

Uno de los requisitos es que cuando recorre los datos del artículo de pedido, si un determinado atributo del producto está vacío, emite una solicitud para obtener datos específicos a través de un modelo separado (funciona bien).

el código del problema básicamente se reduce a esto

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

Sin embargo, Magento está lanzando una excepción 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}

¿Por qué podría usar un código idéntico en un script de terceros fuera del observador de magento bien, pero cuando trato de ejecutarlo dentro de ese observador, falla con ese mensaje de error aleatorio?

Zxurian
fuente
Este error es típico de una no matriz en la que se analiza foreach. El seguimiento de la pila muestra que se envía un evento y que el observador está defectuoso. ¿Estás seguro de que $order->getAllItems()está volviendo a sintonizar array()? utilizar: Zend_Debug::dump($order->getAllItems());. Sin embargo, ¿podría ser otro observador con algún código incorrecto?
ceniza
El problema es con el código central de Magento, no con mi fragmento en la parte superior.
Zxurian

Respuestas:

33

El problema es que no puede guardar productos de la interfaz.

Esto se hace a través del hecho de que cuando carga un producto en la interfaz, la origDatapropiedad no se llena:

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

    return $this;
}

Entonces, cuando intenta guardar el producto, se genera el error que describe.

Puede resolver este problema cuando cambie la tienda actual a admin, por ejemplo, con el código de @magboy:

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

mejor usando Mage_Core_Model_App_Emulation

Y mi solución preferida es extender Mage_Catalog_Model_Producty reemplazar el setOrigDatamétodo

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

¡ NO estoy hablando de una reescritura aquí! Solo use su modelo en este lugar para habilitar el guardado. Entonces tiene la característica de seguridad todavía activa en cualquier otro lugar.

Fabian Blechschmidt
fuente
7

Intente agregar esta línea de código:

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

No estoy seguro de por qué tienes que hacer esto ahora en la versión actual de Magento. Tal vez alguien más puede explicar?

magboy
fuente
después de configurar el almacén actual en Admin y guardar el producto, ¿tengo que volver a establecerlo en el valor original?
Giuseppe
1
@Giuseppe Depende de lo que esté haciendo más adelante con la solicitud; es más limpio y generará menos problemas si lo hace
simonthesorcerer