2

I would like to set a quote's shipping method based on the items selected in the quote (only if there is not already a shipping method selected) and unset the quote's shipping method when there are no more items in the cart/quote.

However, I'm having difficulty with part 2 of this problem. I have tried observing sales_quote_address_save_before, sales_quote_save_after and checkout_cart_save_after and they all exhibit a very odd behavior:

If I add or remove items from the cart, these events fire twice with the new number of items in the cart (so for example, if I had 1 item and added 1 item, it would fire twice with 2 items in the model).

However, if I remove all items from the cart, all three events only fire once with the old number of items in the cart (for example, if I had 1 item in the cart and delete it, the event fires once with 1 item in the model, not 0).

Is there an event that I can use to tell when I have no items in the cart?

4

What works well for me to react on cart changes is a combination of these events:

  • checkout_cart_save_after
  • customer_login
  • customer_logout
  • checkout_onepage_controller_success_action

However, if I remove all items from the cart, all three events only fire once with the old number of items in the cart (for example, if I had 1 item in the cart and delete it, the event fires once with 1 item in the model, not 0).

You are probably looking at the wrong data. When items are removed from the cart, the objects get a deleted flag but stay in the collection. If you use $cart->getItems() or $cart->getItemsCollection() these deleted items are included. Use $cart->getQuote()->getAllItems() or $cart->getQuote()->getAllVisibleItems() instead.

I explained the difference between these methods in: How to get all items in cart currently?

  • I ended up solving my problem in a different way, but you seemed to have the most in-depth response, so you get the check. Thanks! – AlexMax Mar 22 '16 at 15:43
2

I ended up changing how my logic works so instead of observing adding or removing items from cart, I observe controller_action_predispatch_checkout_onepage_index and choose the default shipping method at that point based on the contents of my cart.

1

You can use the sales_quote_remove_item event. The removed item is passed to the observer as an argument.

Mage::dispatchEvent('sales_quote_remove_item', array('quote_item' => $item));

Next, you just need to make sure that there are no items left in the quote. The observer method should look like this:

public function removeShipping(Varien_Event_Observer $observer) 
{
    $quote = $observer->getQuoteItem()->getQuote();

    if (!$quote->getItemsCount()) {
        //remove shipping
    }
}

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.