0

As title says, how can I prevent adding same product to cart more than one time in Magento 2.4.2?

2

This plugin will work for simple and configurable products. You can throw an error or redirect e.g. to cart if product already exists in cart.

di.xml

<type name="Magento\Checkout\Model\Cart">
    <plugin disabled="false" name="Vendor_Module_Plugin_Magento_Checkout_Cart_BeforeAddToCart" type="Vendor\Module\Plugin\Magento\Checkout\Cart\BeforeAddToCart"/>
</type>

vendor/module/Plugin/Magento/Checkout/Cart/BeforeAddToCart.php

    <?php
    declare(strict_types=1);
    
    namespace Vendor\Module\Plugin\Magento\Checkout\Cart;
use Magento\Checkout\Model\Cart;
use Magento\Checkout\Model\Session;
use Magento\Catalog\Model\Product;
use Magento\Checkout\Model\Session\Proxy as SessionProxy;
use Magento\Framework\Message\ManagerInterface;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
use Magento\Framework\UrlInterface;

class BeforeAddToCart {

    private $messageManager;
    private $cartSession;
    private $configurableProduct;
    private $url;
    private $session;

    public function __construct(
        Configurable $configurableProduct,
        ManagerInterface $messageManager,
        SessionProxy $cartSession,
        UrlInterface $url,
        Session $session
    ) {
        $this->messageManager = $messageManager;
        $this->cartSession = $cartSession;
        $this->configurableProduct = $configurableProduct;
        $this->url = $url;
        $this->session = $session;
    }

    public function beforeAddProduct(Cart $subject, $productInfo, $requestInfo=null)
    {
        $enableProductCartControl=true;

        $product = null;
        $parentProduct=null;

        if ($productInfo instanceof Product) {

            $product = $productInfo;
            if (!$product->getId()) {
                throw new \Magento\Framework\Exception\LocalizedException(
                    __("This product wasn't found. Verify the product and try again.")
                );
            }

        }

        if ($product)
        {
            // default product is simple
            //
            if ($product->getTypeId()==='configurable')
            {
                if (isset($requestInfo['super_attribute']))
                {
                    $parentProduct=$product;
                    $childProduct = $this->configurableProduct->getProductByAttributes($requestInfo['super_attribute'] ,$product);
                    // change $product to child
                    $product=$childProduct;
                }
            }

                if ($product && $enableProductCartControl)
                {
                    // check for existence of product in cart...
                    if($this->cartSession->getQuote()->hasProductId($product->getId())){

                        // redirect to cart
                        $this->session->setRedirectUrl($this->url->getUrl('checkout/cart/index'));
                        throw new \Magento\Framework\Exception\LocalizedException(
                            __("[x] This product is already in the cart. Testing, testing : ". $product->getSku())
                        );
                    }

                }


        }

        return [$productInfo, $requestInfo];

    }

    /**
     * Get request for product add to cart procedure
     *
     * @param \Magento\Framework\DataObject|int|array $requestInfo
     * @return \Magento\Framework\DataObject
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    private function _getProductRequest($requestInfo)
    {
        if ($requestInfo instanceof \Magento\Framework\DataObject) {
            $request = $requestInfo;
        } elseif (is_numeric($requestInfo)) {
            $request = new \Magento\Framework\DataObject(['qty' => $requestInfo]);
        } elseif (is_array($requestInfo)) {
            $request = new \Magento\Framework\DataObject($requestInfo);
        } else {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('We found an invalid request for adding product to quote.')
            );
        }
        return $request;
    }
}
17
  • Thanks. I tested it on my store which has only configurable products which all contain 2 simple products and 1 downloadable product inside, but it doesn't work. I cannot add any product to the cart anymore.
    – KaMZaTa
    Feb 23 '21 at 16:08
  • Check your logs for errors, the code works fine for me.
    – paj
    Feb 23 '21 at 16:17
  • There's nothing on Magento logs. It simply refreshes the page but nothing is added to the cart.
    – KaMZaTa
    Feb 23 '21 at 16:23
  • You are implementing this in your own module right? You know "vendor/Module" should be replaced with your own module path?
    – paj
    Feb 23 '21 at 16:29
  • Yes, I implemented it in my module. Yes, I replaced Vendor/Module with my own path.
    – KaMZaTa
    Feb 23 '21 at 16:48
1

You can use plugin for that

in you di.xml

<type name="Magento\Checkout\Model\Cart">
<plugin name="prevent_add_to" type="vendor\Module\Plugin\Beforeaddtocart"/>
</type>

vendor\Module\Plugin\Beforeaddtocart.php

<?php

namespace vendor\Module\Plugin;

class Beforeaddtocart{
    
    public function beforeAddProduct(\Magento\Checkout\Model\Cart $subject, $productInfo, $requestInfo=null){
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $session = $objectManager->create('\Magento\Checkout\Model\Session');
        
        $product_id = $requestInfo['product'];
        $quote = $session->getQuote()->hasProductId($product_id);
        if($quote){
            throw new \Magento\Framework\Exception\LocalizedException(
                    __("The product is already in cart you can't add more than 1 qty")
                );
        }
        return [$productInfo, $requestInfo];

    }
}

note: Please don't use objectmanager directly

4
  • This code will not work for variations of configurable products added to cart.
    – paj
    Feb 23 '21 at 11:27
  • Thanks, but since my store has only configurable products which contain 2 simple products and 1 downloadable product, how can I adapt it in order to prevent to add just 1 kind of these products and not the whole configurable product?
    – KaMZaTa
    Feb 23 '21 at 16:10
  • Anyway, it seems to work for the whole configurable product (but not for the child, as I wrote)
    – KaMZaTa
    Feb 23 '21 at 16:50
  • sorry the code was not tested. but yes that code not work for configurable product
    – Ronak
    Feb 24 '21 at 4:00

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.