Awaria Magento podczas próby zapisania produktu w obserwatorze zdarzeń na interfejsie?

15

Mam funkcję powiązaną z obserwatorem zdarzeń

Jednym z wymagań jest to, że kiedy przechodzi przez dane pozycji zamówienia, jeśli określony atrybut produktu jest pusty, wysyła żądanie uzyskania określonych danych przez oddzielny model (działa dobrze).

kod problemu sprowadza się do tego

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

jednak Magento zgłasza wyjątek

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}

Dlaczego miałbym móc używać identycznego kodu w skrypcie innej firmy poza obserwatorem magento, ale kiedy próbuję uruchomić go w tym obserwatorze, komunikat o błędzie pojawia się losowo?

Zxurian
źródło
Ten błąd jest typowy dla analizowanego zestawu nie-tablicowego foreach. Ślad stosu pokazuje, że zdarzenie zostało wysłane, a obserwator jest uszkodzony. Czy na pewno $order->getAllItems()się stroi array()? używać: Zend_Debug::dump($order->getAllItems());. Jednak może to być kolejny obserwator z jakimś złym kodem?
ash
problem dotyczy kodu rdzenia Magento, a nie mojego fragmentu u góry.
Zxurian

Odpowiedzi:

33

Problem polega na tym, że nie możesz zapisywać produktów z interfejsu.

Odbywa się to poprzez fakt, że podczas ładowania produktu w interfejsie origDatawłaściwość nie jest wypełniona:

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

    return $this;
}

Gdy więc próbujesz zapisać produkt, pojawia się opisany błąd.

Możesz rozwiązać ten problem, zmieniając bieżący sklep na admin, np. Za pomocą kodu z @magboy:

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

lepsze użycie Mage_Core_Model_App_Emulation

A moim preferowanym rozwiązaniem jest rozszerzenie Mage_Catalog_Model_Producti zastąpienie setOrigDatametody

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

Ja nie mówić o przepisanie tutaj! Używaj swojego modelu tylko w tym jednym miejscu, aby umożliwić zapisywanie. Dzięki temu funkcja bezpieczeństwa jest nadal aktywna wszędzie indziej.

Fabian Blechschmidt
źródło
7

Spróbuj dodać ten wiersz kodu:

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

Nie jestem pewien, dlaczego musisz to zrobić teraz w bieżącej wersji Magento. Może ktoś inny może to wyjaśnić?

magboy
źródło
po ustawieniu bieżącej przechowalni na Administratora i zapisaniu produktu, czy muszę przywracać pierwotną wartość?
Giuseppe
1
@Giuseppe Zależy to, co zrobisz później z prośbą; jest czystszy i przyniesie mniej problemów, jeśli to zrobisz
simonthesorcerer