2

I am working on a custom module that adds two products together - a setup product and a unit product (for example a setup charge for custom graphics and then a unit charge for the number of applications of those graphics)

My problem is that when a visitor removes either the setup or the unit product, I need to remove both products.

I am using the event listener: sales_quote_remove_item

my observer method looks something like this:

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

The problem that I am having is that each call to remove a product from the cart fires the sales_quote_remove_item event which creates an infinite loop.

Any suggestions?

  • It should only call 'item removed' + 1 because it will trigger after the last item is remove but after that nothing else is there to remove so it should stop – Renon Stewart Oct 30 '14 at 18:51
  • @R.S It fires the event when the product is removed from the cart, but before the quote is saved and finalized. So the registry still has the requested product to delete and because I have to look up the customization product for the product being removed, it tries to remove it again. Even though zero products were removed, it knows that there was a request to remove a product, so it fires again. Setting a custom registry flag did the trick. – Jon Oct 30 '14 at 18:58
1

Instead of

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

you should use something like this:

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

The key here is that removing an item, sets the is_deleted flag and with this you can check if an item is already flagged for deletion. Also you don't need to save each one individually as long as the cart gets saved in the end.

1

I fixed the infinite loop observer by changing my observer method to something like this:

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

Found the answer over here: https://stackoverflow.com/questions/10841208/prevent-the-trigger-of-observer-in-magento

  • 1
    This seems hacky and doesn't seem like it will work with an arbitrary number of items. fschmengler's solution seems more sound. I also encourage you to upvote, if you found something useful, to help this community. – musicliftsme Jan 31 '15 at 23:43
  • Maybe a bit hacky but is the same what came to my mind after reading the topic. Only I would have used a static property inside the observer or made the observer singleton. But yes, it does not work with an arbitrary number of items. – Flyingmana Feb 1 '15 at 7:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.