Ограничить добавление в корзину только одним товаром в корзину в magento 2
Как ограничить корзину в magento только одним товаром на одного клиента?
3 answers
Хотя решение, предоставленное @Jigs-Parmar, также должно работать, вы также можете сделать это с помощью плагина.
Ниже приведены основные шаги:
App/code/SR/Stackexchange/etc/frontend/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Model\Cart">
<plugin name="SR_Stackexchange::add_to_cart" type="SR\Stackexchange\Plugin\Checkout\Model\Cart" sortOrder="1"/>
</type>
</config>
App/code/SR/Stackexchange/Plugin/Checkout/Model/Cart.php
namespace SR\Stackexchange\Plugin\Checkout\Model;
use Magento\Catalog\Model\Product;
class Cart
{
/**
* @var \Magento\Checkout\Model\Session
*/
protected $checkoutSession;
/**
* Cart constructor.
*
* @param \Magento\Checkout\Model\Session $checkoutSession
*/
public function __construct(
\Magento\Checkout\Model\Session $checkoutSession
) {
$this->checkoutSession = $checkoutSession;
}
/**
* @param \Magento\Checkout\Model\Cart $subject
* @param \Closure $proceed
* @param $productInfo
* @param null $requestInfo
* @return mixed
*/
public function aroundAddProduct(
\Magento\Checkout\Model\Cart $subject,
\Closure $proceed,
$productInfo,
$requestInfo = null
) {
if ($productInfo instanceof Product) {
$productId = $productInfo->getId();
} elseif (is_int($productInfo) || is_string($productInfo)) {
$productId = $productInfo;
} else {
return $proceed($productInfo, $requestInfo);
}
$isSameProduct = 0;
$quote = $this->checkoutSession->getQuote();
$items = $quote->getAllItems();
foreach ($items as $item) {
if($productId == $item->getProductId()) {
$isSameProduct = 1;
break;
}
}
if($isSameProduct) {
return $proceed($productInfo, $requestInfo);
}
$quote->removeAllItems()->save();
return $proceed($productInfo, $requestInfo);
}
}
Теперь вам нужно изменить при объединении цитату после входа в систему:
App/code/SR/Stackexchange/etc/frontend/events.xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="sales_quote_merge_before">
<observer name="SR_Stackexchange_sales_quote_merge_before" instance="SR\Stackexchange\Observer\SalesQuoteMergeBefore"/>
</event>
</config>
App/code/SR/Stackexchange/Observer/SalesQuoteMergeBefore.php
namespace SR\Stackexchange\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
class SalesQuoteMergeBefore implements ObserverInterface
{
/**
* Avoid shopping carts merging on customer login
*
* @param EventObserver $observer
*/
public function execute(EventObserver $observer)
{
if ($observer->getSource()->hasItems()) {
$currentQuote = $observer->getSource();
$productId = 0;
foreach ($currentQuote->getAllVisibleItems() as $item) {
$productId = $item->getProductId();
}
if (is_object($observer->getQuote()) && $observer->getQuote()->getId()) {
$oldQuote = $observer->getQuote();
$hasSameProduct = 0;
foreach ($oldQuote->getAllVisibleItems() as $item) {
if($productId == $item->getProductId()) {
$hasSameProduct = 1;
}
}
if($hasSameProduct == 0) {
$observer->getQuote()->removeAllItems();
}
}
}
}
}
Очистить кэш.
Примечание: Вы можете изменить 'SR/Stackexchange' свое собственное имя модуля
Примечание: Я предполагаю, что вы хотите удалять последний добавленный товар каждый раз, когда в корзину добавляется новый товар. Пожалуйста, внесите необходимые изменения в класс плагина, если вы хотите сохранить старый элемент и показать клиенту только сообщение о том, что новый элемент не может быть добавлен.
Дайте мне знать, если это не так работайте или если у вас есть запрос.
Поскольку ответ не принимается, около плагинов (используемых в ответе Мохита) не рекомендуется Magento, и ответ Джигса кажется чрезмерным и может не сработать, если другие расширения подключаются к тому же наблюдателю, я решил поделиться своим собственным ответом.
Я предполагаю, что вы знаете, как построить основы модуля (registration.php
, module.xml
, и т.д.)
Этот модуль перенаправляет пользователя в корзину и показывает ошибку, предлагая пользователю сначала завершить этот заказ и разместить другой.
Daan/LimitCartItems/etc/frontend/events.xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="controller_action_predispatch_checkout_cart_add">
<observer name="daan_limit_items_in_cart_checkout_before" instance="Daan\LimitCartItems\Observer\Checkout\Cart\Add" />
</event>
</config>
Daan/LimitCartItems/Observer/Checkout/Cart/Add.php
<?php
namespace Daan\LimitCartItems\Observer\Checkout\Cart;
use Magento\Checkout\Model\Session;
use Magento\Framework\App\ActionFlag;
use Magento\Framework\App\Response\RedirectInterface as ResponseRedirect;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Message\ManagerInterface as MessageManager;
class Add implements ObserverInterface
{
/** @var Session $session */
private $session;
/** @var ActionFlag $flag */
private $flag;
/** @var ResponseRedirect $redirect */
private $redirect;
/** @var MessageManager $messageManager */
private $messageManager;
/**
* Add constructor.
*
* @param Session $session
* @param ActionFlag $flag
* @param ResponseRedirect $redirect
* @param MessageManager $messageManager
*/
public function __construct(
Session $session,
ActionFlag $flag,
ResponseRedirect $redirect,
MessageManager $messageManager
) {
$this->session = $session;
$this->flag = $flag;
$this->redirect = $redirect;
$this->messageManager = $messageManager;
}
/**
* @param Observer $observer
*
* @return $this|void
* @throws \Magento\Framework\Exception\LocalizedException
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function execute(Observer $observer)
{
$quote = $this->session->getQuote();
$itemsCount = $quote->getItemsCount();
if ($itemsCount >= 1) {
$request = $observer->getRequest();
$request->setParams([
'product' => false,
'return_url' => $this->redirect->getRefererUrl(),
'backUrl' => $this->redirect->getRefererUrl()
]);
$this->messageManager->addErrorMessage(
__('Only one product per purchase allowed. Please complete this order first and place another order afterwards.')
);
$action = $observer->getEvent()->getControllerAction();
$this->flag->set('', \Magento\Framework\App\ActionInterface::FLAG_NO_DISPATCH, true);
$action->getResponse()->setRedirect('/checkout/cart');
return $this;
}
}
}
Создать event.xml файл в папке etc
И напишите ниже код
<event name="controller_action_predispatch_checkout_cart_add">
<observer name="restrict_sales_model_cart_add_before" instance="Vendor\Module\Observer\Cartadd" />
</event>
Теперь создайте Cartadd.php в папке Obsever
<?php
namespace Vendor\Module\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\App\ObjectManager;
class Cartadd implements ObserverInterface {
protected $_urlManager;
protected $_checkoutSession;
protected $_cart;
protected $_messageManager;
protected $_redirect;
protected $_request;
protected $_response;
protected $_responseFactory;
protected $_resultFactory;
protected $_scopeConfig;
protected $_product;
public function __construct(\Magento\Framework\UrlInterface $urlManager, \Magento\Checkout\Model\Session $checkoutSession, \Magento\Framework\App\Response\RedirectInterface $redirect, \Magento\Checkout\Model\Cart $cart, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Framework\App\RequestInterface $request, \Magento\Framework\App\ResponseInterface $response, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Catalog\Model\Product $product, \Magento\Framework\App\ResponseFactory $responseFactory, \Magento\Framework\Controller\ResultFactory $resultFactory
) {
$this->_urlManager = $urlManager;
$this->_checkoutSession = $checkoutSession;
$this->_redirect = $redirect;
$this->_cart = $cart;
$this->_messageManager = $messageManager;
$this->_request = $request;
$this->_response = $response;
$this->_responseFactory = $responseFactory;
$this->_resultFactory = $resultFactory;
$this->_scopeConfig = $scopeConfig;
$this->_product = $product;
}
public function execute(\Magento\Framework\Event\Observer $observer) {
$controller = $observer->getControllerAction();
$postValues = $this->_request->getPostValue();
$cartQuote = $this->_cart->getQuote()->getData();
$cartItemsCount = $this->_cart->getQuote()->getItemsCount();
$cartItemsAll = $this->_cart->getQuote()->getAllItems();
if($cartItemsCount > 0)
{
$observer->getRequest()->setParam('product', false);
$observer->getRequest()->setParam('return_url', $this->_redirect->getRefererUrl());
$observer->getRequest()->setParam('backUrl', $this->_redirect->getRefererUrl());
$this->_messageManager->addError(__('Only 1 product Allowed to Purchase at a time.'));
}
}
}