18

We have a requirement, wherein a customer will be allowed to add only one product to the cart at a time. However he/she can add any quantity of that product.

How can I prevent a product from adding to cart if there is already a product present in the cart?

Can some one help on this?

2

6 Answers 6

21

The events catalog_product_type_prepare_full_options and catalog_product_type_prepare_lite_options are your friends

<?xml version="1.0"?>
<config>
    <modules>
        <Fooman_Example>
            <version>0.1.0</version>
        </Fooman_Example>
    </modules>
    <global>
        <models>
            <fooman_example>
                <class>Fooman_Example_Model</class>
            </fooman_example>
        </models>
        <helpers>
            <fooman_example>
                <class>Fooman_Example_Helper</class>
            </fooman_example>
        </helpers>
    </global>
    <frontend>
        <events>
            <catalog_product_type_prepare_full_options>
                <observers>
                    <fooman_example_catalog_product_type_prepare>
                        <class>Fooman_Example_Model_Observer</class>
                        <method>catalogProductTypePrepare</method>
                    </fooman_example_catalog_product_type_prepare>
                </observers>
            </catalog_product_type_prepare_full_options>
        </events>
    </frontend>
</config>

Then in your Observer class

<?php

class Fooman_Example_Model_Observer
{
    public function catalogProductTypePrepare($observer)
    {
        $quote = Mage::getSingleton('checkout/session')->getQuote();
        if($quote->getItemsCount()>=1){
            Mage::throwException('You can only buy one product at a time.');
        }
    }
}
4
  • catalog_product_type_prepare_lite_options is a first for me! nicely done.
    – philwinkle
    Oct 17, 2013 at 17:16
  • 4
    @philwinkle it comes in very handy for anything just before adding to cart. I think it gets missed from a lot of cheatsheets because a normal grep only produces Mage::dispatchEvent($eventName, missing the preceding line $eventName = sprintf('catalog_product_type_prepare_%s_options', $processMode); Oct 17, 2013 at 17:29
  • well that worked like a charm. Dec 7, 2015 at 9:46
  • Fooman,it is grts me
    – Amit Bera
    Jun 4, 2016 at 5:19
8

Instead of rewriting a controller (please oh please don't do that), rather, rewrite the addProduct method to account for the limit:

class YourCompany_YourModule_Model_Cart extends Mage_Checkout_Model_Cart
{
    public function addProduct($productInfo, $requestInfo=null){
        if($this->getItemsCount()>1){
            Mage::throwException(Mage::helper('checkout')->__('Cannot add item - cart quantity would exceed checkout the limit of %s per person.', 1));
        }
        parent::addProduct($productInfo, $requestInfo);
    }
}

If you want to get fancy, replace the 1 above with Mage::getStoreConfig('checkout/options/max_cart_qty) and set the following your module's config.xml:

<default>
    <checkout>
        <options>
            <max_cart_qty>1</max_cart_qty>
        </options>
    </checkout>
</default>

That value is now controlled via the XML value. If you want to get really, really fancy, add this to the system.xml of your new module:

<config>
    <sections>
        <checkout>
            <groups>
                <options>
                    <fields>
                        <max_cart_qty translate="label">
                            <label>Maximum Quantity Allowed in Cart (total qty)</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>100</sort_order>
                            <show_in_default>1</show_in_default>
                        </max_cart_qty>
                    </fields>
                </options>
            </groups>
        </checkout>
    </sections>
</config>

Remember that you need to set a <depends>Mage_Checkout</depends> to your module in order to piggyback on its' predefined system configuration.

2
  • Thanks a lot, your answer is "really fancy", but Fooman's answer was in line with what i was already trying, so accepted that as the answer. But if I haven't started using observers, I would have used your method :).
    – Shathish
    Oct 18, 2013 at 4:35
  • 1
    Of course! @fooman was right on - this was educational for me, too :)
    – philwinkle
    Oct 18, 2013 at 15:03
2

A possible way is to rewrite the addAction of Mage_Checkout_CartController.

So check if there is already a product in cart and if yes show an appropriate error message. If not you can call the parent method which is doing the complete add-process:

    if (count($this->_getCart()->getProductIds()) > 0) {
        $this->_goBack();
    } else {
        parent::addAction();
    }
5
  • I am sorry, $this->_goBack(); doesn't work! I get into the if condition but the product is still getting added.
    – Shathish
    Oct 17, 2013 at 12:25
  • What happens if you just exit at that point, just to debug what's really happening, because the whole addAction process should not be executed
    – Tobias
    Oct 17, 2013 at 12:44
  • giving exit at that point exits the execution giving me a blank screen
    – Shathish
    Oct 17, 2013 at 13:00
  • but does it add the product?
    – Tobias
    Oct 17, 2013 at 13:14
  • 3
    please oh please do not rewrite controllers
    – philwinkle
    Oct 17, 2013 at 14:20
1

I think you can use an observer and the following events will be useful to check the conditions what you want. (Perhaps some of the events may not in the version of Magento that you are using).

checkout_cart_save_before

checkout_cart_product_add_after

checkout_cart_update_items_before

checkout_cart_update_items_after

checkout_cart_save_after
2
  • I'm already trying with checkout_cart_product_add_after event, the question is how can I prevent the product from getting added to cart?
    – Shathish
    Oct 17, 2013 at 11:43
  • or if it is already added, how to remove it?
    – Shathish
    Oct 17, 2013 at 11:49
1

Maybe a bit of a left field idea but how about using the catalog_product_is_salable_after event?

What you can do here is check to see if the product is in the cart or if there is another product in the cart. When there is another product in the cart update the 'is_salable' attribute of the 'salable' object passed to the observer to false.

NOTE that this has not been tested and is only an idea. It will fail if your template does not check $product->isSaleable() before displaying the button. It would also only remove the button and not actually stop the add process if the user was able to guess the url.

1

I know this topic is something old, but i had a similar problem. I want only one item in cart and if customer adds a new one, i want to replace the old one with the new one. So i override the addAction (described here like this:

public function addAction(){
    $items = $this->_getCart()->getItems();
            foreach ($items as $item)
                    {
                            $itemId = $item->getItemId();
                            $this->_getCart()->removeItem($itemId);
                    }
    parent::addAction();

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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