As title says, how can I prevent adding same product to cart more than one time in Magento 2.4.2?
2 Answers
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;
}
}
-
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.– KaMZaTaFeb 23, 2021 at 16:08
-
-
There's nothing on Magento logs. It simply refreshes the page but nothing is added to the cart.– KaMZaTaFeb 23, 2021 at 16:23
-
You are implementing this in your own module right? You know "vendor/Module" should be replaced with your own module path?– pajFeb 23, 2021 at 16:29
-
Yes, I implemented it in my module. Yes, I replaced Vendor/Module with my own path.– KaMZaTaFeb 23, 2021 at 16:48
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
-
This code will not work for variations of configurable products added to cart.– pajFeb 23, 2021 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?– KaMZaTaFeb 23, 2021 at 16:10
-
Anyway, it seems to work for the whole configurable product (but not for the child, as I wrote)– KaMZaTaFeb 23, 2021 at 16:50
-
sorry the code was not tested. but yes that code not work for configurable product– RonakFeb 24, 2021 at 4:00