14

What I want to do is if my custom attribute is set in quote then i do not want any product to be added in cart. My custom attribute is being set correctly.

To stop product from getting added to cart, I have written an Observer which observes this event controller_action_predispatch_checkout_cart_add

My observer file code:

public function execute(\Magento\Framework\Event\Observer $observer) {
    $addedItemId = $observer->getRequest()->getParam('product');
    $quote       = $this->_cart->getQuote();

    if(!empty($quote)) {
        $customAttribute = $quote->getData('custom_attribute');

        if(!empty($customAttribute)) {
             $controller = $observer->getControllerAction();
             $storeId     = $this->_objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore()->getId();
             $product    = $this->_productRepository->getById($addedItemId, false, $storeId);
             $observer->getRequest()->setParam('product', null);

             $this->_messageManager->addError(__('This product cannot be added to your cart.'));
             echo false;            

             $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
             $this->redirect->redirect($controller->getResponse(), 'checkout/cart/index');          
        }
    }       
}

With this code, I am able not able to stop the add to cart process.

So as per this answer of Magento1 - https://stackoverflow.com/questions/14190358/stop-add-to-cart-and-supply-message-to-user-in-magento . I tried replacing

$this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
$this->redirect->redirect($controller->getResponse(), 'checkout/cart/index');  

with (This is not the best way of doing it. If there is any better way, please suggest)

header("Location: " . $product->getProductUrl());
die();

This ultimately stops the add to cart process but the add to cart button still keeps on showing "Adding". How can i perform this correctly so that add to cart button goes back to its previous state and the product too does not get added to cart ?

enter image description here

5
  • hi @reena can you help me how you did that
    – mcoder
    Apr 18, 2016 at 10:15
  • @mcoder - i did it with a plugin. u can refer the accepted answer below for more details. Apr 18, 2016 at 11:12
  • i tried but can not do can you please help me how you did that i have same issue as you see what i tried : magento.stackexchange.com/questions/111231/… but it did not worked
    – mcoder
    Apr 18, 2016 at 13:07
  • i want to redirect to external url like google.com i tried below one it redirect to to ajax add cart url , i am stuck for two days but could not do it :(. I will try to donate for you help
    – mcoder
    Apr 18, 2016 at 13:10
  • How can you get solution?? can you give me all the file whith code ? i have the same problem Mar 22, 2018 at 10:48

3 Answers 3

26

you could try to set the product param to false and then set the return_url param:

$observer->getRequest()->setParam('product', false);
$observer->getRequest()->setParam('return_url', $this->_redirect->getRefererUrl());
$this->_messageManager->addError(__('This product cannot be added to your cart.'));

The cart controller checks if the product param is set here: https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L99

and if it is not, it calls goBack. the goBack method checks if you made an ajax request (I think you did) and then returns an additional param backUrl in the ajax response.

https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L165

The getBackUrl method then returns the return_url param:

https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart.php#L113

===UPDATE===

ok since the message adding does not work here, you should try another way (it's also more straight forward)

create a Plugin to Intercetp before this function: https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Model/Cart.php#L341

If you do not want your product added, just throw an Exception with the desired Message. You find a nice tutorial for creating plugins here: http://alanstorm.com/magento_2_object_manager_plugin_system

The Product adding should be interrupted and the Exception should be rendered as message https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L137

add the following type to your modules etc/frontend/di.xml

<type name="Magento\Checkout\Model\Cart">
    <plugin name="interceptAddingProductToCart"
            type="Vendor\Module\Model\Checkout\Cart\Plugin"
            sortOrder="10"
            disabled="false"/>
</type>

Then the class Vendor/Module/Model/Checkout/Cart/Plugin should look like this:

<?php
namespace Vendor\Module\Model\Checkout\Cart;

use Magento\Framework\Exception\LocalizedException;

class Plugin
{
    /**
     * @var \Magento\Quote\Model\Quote
     */
    protected $quote;

    /**
     * Plugin constructor.
     *
     * @param \Magento\Checkout\Model\Session $checkoutSession
     */
    public function __construct(
        \Magento\Checkout\Model\Session $checkoutSession
    ) {
        $this->quote = $checkoutSession->getQuote();
    }

    /**
     * beforeAddProduct
     *
     * @param      $subject
     * @param      $productInfo
     * @param null $requestInfo
     *
     * @return array
     * @throws LocalizedException
     */
    public function beforeAddProduct($subject, $productInfo, $requestInfo = null)
    {
        if ($this->quote->hasData('custom_attribute')) {
            throw new LocalizedException(__('Could not add Product to Cart'));
        }

        return [$productInfo, $requestInfo];
    }
}
6
  • 1
    Thank you David. Your solution works, upvote from me. However, the error message does not get displayed. I am assuming because of this line : github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/… ? Can you suggest how can i resolve that ? Feb 13, 2016 at 6:23
  • 1
    yes, jut added another solution. Be sure to clean the var/generation folder and the configuration cache to have these changes applied Feb 13, 2016 at 7:10
  • Used your 1st method but not able to get the error message, How can i set the return url and message in your 2nd method.
    – Amit Singh
    Dec 29, 2016 at 11:25
  • 1
    Can you tell, how can I get custom option values here?
    – anujeet
    Apr 24, 2017 at 10:12
  • @DavidVerholen - +1 from my side !! btw How to get Product Id over here in beforeAddProduct function !!! Mar 7, 2018 at 10:16
3

Below is my code to stop product from being added to cart and display error message using observer.

<?php
use Magento\Framework\Event\ObserverInterface;

class ProductAddCartBefore implements ObserverInterface
{

    protected $_request;
    protected $_checkoutSession;
    protected $_messageManager;

    public function __construct(
        \Magento\Framework\App\RequestInterface $request,  
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Checkout\Model\SessionFactory $checkoutSession
    )
    {
        $this->_request = $request;
        $this->_messageManager = $messageManager;
        $this->_checkoutSession = $checkoutSession;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $productId = $observer->getRequest()->getParam('product');

        $quote = $this->_checkoutSession->create()->getQuote();

        $itemsCount = $quote->getItemsSummaryQty();

        if($itemsCount > 0 && $productId != 1949)
        {
            if($quote->hasProductId(1949)) 
            {   
                $observer->getRequest()->setParam('product', false);
                $observer->getRequest()->setParam('return_url', false);
                $this->_messageManager->addErrorMessage(__('To proceed please remove other items from the cart.'));
            }
        }
    }
}

you can set the conditions as per your requirements to prevent product from adding to cart.

2
  • This worked for me. Feb 3, 2020 at 16:25
  • @SiranjeeviKS I have used "controller_action_predispatch_checkout_cart_add" event for this observer.
    – Vips Lucky
    Jul 14, 2020 at 10:28
0

Remove the last three line code

And add this one line: return false; And set value of product param: false Then you get error message and loader is hide... Thanks

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.