Проблема с наблюдателем рекурсивных событий при удалении элементов предложения


Я работаю над пользовательским модулем, который объединяет два продукта - продукт настройки и единичный продукт (например, плата за настройку пользовательской графики, а затем плата за единицу за количество приложений этой графики)

Моя проблема заключается в том, что, когда посетитель удаляет либо установку, либо единичный продукт, мне нужно удалить оба продукта.

Я использую прослушиватель событий: sales_quote_remove_item

Мой метод наблюдателя выглядит примерно так это:

public function removeCustomizationItems(Varien_Event_Observer $observer) {
    $_product_id = $observer->getQuoteItem()->getProduct()->getId();

    // returns an array of customization product pairs (setup=>id, unit=>id, min_qty=>(int))
    $_target_products = Mage::helper('hq_customization')->getTargetProducts();

    foreach ($_target_products as $_target_product) {
        if ($_product_id == $_target_product['setup'] || $_product_id == $_target_product['unit']) {
            $this->removeItems($_target_product);
        }
    }
}
public function removeItems($_target_product) {
    if (!empty($_target_product['setup'])) $_remove_ids[] = $_target_product['setup'];
    if (!empty($_target_product['unit'])) $_remove_ids[] = $_target_product['unit'];

    $cartHelper = Mage::helper('checkout/cart');
    $items = $cartHelper->getCart()->getItems();

    foreach ($items as $item) {
        $itemId = $item->getItemId();
        $prodId = $item->getProductId();

        if (in_array($prodId, $_remove_ids)) $cartHelper->getCart()->removeItem($itemId)->save();
    }
}

Проблема, с которой я сталкиваюсь, заключается в том, что каждый вызов для удаления товара из корзины запускает событие sales_quote_remove_item, которое создает бесконечный цикл.

Есть какие-нибудь предложения?

Author: Fabian Schmengler, 2014-10-30

2 answers

Вместо

    if (in_array($prodId, $_remove_ids)) $cartHelper->getCart()->removeItem($itemId)->save();

Вы должны использовать что-то вроде этого:

    if (in_array($prodId, $_remove_ids) && !$quote->getItemById($itemId)->isDeleted())
         $cartHelper->getCart()->removeItem($itemId);

Ключ здесь в том, что удаление элемента устанавливает флаг is_deleted, и с его помощью вы можете проверить, помечен ли элемент уже для удаления. Кроме того, вам не нужно сохранять каждый из них по отдельности, если в конце концов корзина будет сохранена.

 1
Author: Fabian Schmengler, 2014-11-07 23:13:25

Я исправил наблюдателя бесконечного цикла, изменив свой метод наблюдателя на что-то вроде этого:

public function removeCustomizationItems(Varien_Event_Observer $observer) {
    // If this returns true, customization products matched and removed
    if (Mage::registry('hq_customization_product_deleted')) return $this;

    $_product_id = $observer->getQuoteItem()->getProduct()->getId();

    // returns an array of customization product pairs (setup=>id, unit=>id, min_qty=>(int))
    $_target_products = Mage::helper('hq_customization')->getTargetProducts();

    foreach ($_target_products as $_target_product) {
        if ($_product_id == $_target_product['setup'] || $_product_id == $_target_product['unit']) {
            Mage::register('hq_customization_product_deleted', true);
            $this->removeItems($_target_product);
        }
    }
}

Нашел ответ здесь: https://stackoverflow.com/questions/10841208/prevent-the-trigger-of-observer-in-magento

 1
Author: Jon, 2017-05-23 12:37:13