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?

19

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.');
        }
    }
}
  • catalog_product_type_prepare_lite_options is a first for me! nicely done. – philwinkle Oct 17 '13 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); – Kristof at Fooman Oct 17 '13 at 17:29
  • well that worked like a charm. – Deepanshu Goyal Dec 7 '15 at 9:46
  • Fooman,it is grts me – Amit Bera Jun 4 '16 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.

  • 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 '13 at 4:35
  • 1
    Of course! @fooman was right on - this was educational for me, too :) – philwinkle Oct 18 '13 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();
    }
  • I am sorry, $this->_goBack(); doesn't work! I get into the if condition but the product is still getting added. – Shathish Oct 17 '13 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 '13 at 12:44
  • giving exit at that point exits the execution giving me a blank screen – Shathish Oct 17 '13 at 13:00
  • but does it add the product? – Tobias Oct 17 '13 at 13:14
  • 2
    please oh please do not rewrite controllers – philwinkle Oct 17 '13 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
  • 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 '13 at 11:43
  • or if it is already added, how to remove it? – Shathish Oct 17 '13 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, privacy policy and cookie policy

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