Magento2 - Como impedir que um produto seja adicionado ao carrinho de forma programática?

13

O que eu quero fazer é se meu atributo personalizado estiver definido entre aspas, então não quero que nenhum produto seja adicionado ao carrinho. Meu atributo personalizado está sendo definido corretamente.

Para impedir que o produto seja adicionado ao carrinho, escrevi um Observador que observa esse evento controller_action_predispatch_checkout_cart_add

Meu código de arquivo observador:

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');          
        }
    }       
}

Com este código, não consigo parar o processo de adicionar ao carrinho.

Então, de acordo com esta resposta do Magento1 - /programming/14190358/stop-add-to-cart-and-supply-message-to-user-in-magento . Eu tentei substituir

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

with (Esta não é a melhor maneira de fazê-lo. Se houver alguma maneira melhor, por favor sugira)

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

Em última análise, isso interrompe o processo de adicionar ao carrinho, mas o botão Adicionar ao carrinho continua mostrando "Adicionando" . Como posso fazer isso corretamente para que o botão adicionar ao carrinho volte ao seu estado anterior e o produto também não seja adicionado ao carrinho?

insira a descrição da imagem aqui

Reena Parekh
fonte
oi @reena você pode me ajudar como você fez isso
mcoder
@ codificador - eu fiz isso com um plugin. Você pode consultar a resposta aceita abaixo para obter mais detalhes.
Reena Parekh
Eu tentei, mas não pode fazer você pode por favor me ajude como você fez que eu tenho mesmo problema que você vê o que eu tentei: magento.stackexchange.com/questions/111231/... mas não funcionou
mcoder
Eu quero redirecionar para url externo como google.com eu tentei abaixo de um redirecionar para ajax adicionar carrinho url, estou preso por dois dias, mas não conseguiu :(. vou tentar doar para você ajudar
mcoder
Como você pode obter solução? você pode me dar todo o arquivo com código? Eu tenho o mesmo problema
Jigs Parmar

Respostas:

22

você pode tentar definir o parâmetro do produto como false e definir o parâmetro return_url:

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

O controlador do carrinho verifica se o parâmetro do produto está definido aqui: https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L99

e se não for, chama goBack. o método goBack verifica se você fez uma solicitação ajax (acho que você fez) e, em seguida, retorna um parâmetro adicional backUrl na resposta ajax.

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

O método getBackUrl retorna o parâmetro return_url:

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

=== ATUALIZAÇÃO ===

ok, já que a adição da mensagem não funciona aqui, você deve tentar de outra maneira (também é mais direto)

crie um plugin para Intercetp antes desta função: https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Model/Cart.php#L341

Se você não deseja que seu produto seja adicionado, basta lançar uma exceção com a mensagem desejada. Você encontra um bom tutorial para criar plug-ins aqui: http://alanstorm.com/magento_2_object_manager_plugin_system

A adição do produto deve ser interrompida e a exceção deve ser renderizada como mensagem https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L137

adicione o seguinte tipo aos seus módulos 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>

Então a classe Vendor/Module/Model/Checkout/Cart/Plugindeve ficar assim:

<?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];
    }
}
David Verholen
fonte
1
Obrigado David. Sua solução funciona, voto positivo de mim. No entanto, a mensagem de erro não é exibida. Estou assumindo por causa desta linha: github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/… ? Você pode sugerir como posso resolver isso?
Reena Parekh
1
sim, apenas adicionei outra solução. Certifique-se de limpar a pasta var / geração e o cache de configuração para ter estas mudanças aplicadas
David Verholen
Utilizou o seu primeiro método, mas não foi capaz de receber a mensagem de erro. Como posso definir o URL de retorno e a mensagem no seu segundo método.
Amit Singh
1
Você pode dizer, como posso obter valores de opções personalizadas aqui?
precisa saber é o seguinte
+1 Absolutamente brilhante! Solução perfeita (a atualização). Funciona com 2.1.5.
Dave
2

Abaixo está o meu código para impedir que o produto seja adicionado ao carrinho e exibir a mensagem de erro usando o observador.

<?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.'));
            }
        }
    }
}

você pode definir as condições conforme seus requisitos para impedir que o produto seja adicionado ao carrinho.

Vips Lucky
fonte
Isso funcionou para mim.
Hassan Al-Jeshi 03/02
0

Remova o último código de três linhas

E adicione esta linha: return false; E definir o valor do parâmetro do produto: false Então você recebe a mensagem de erro e o carregador está oculto ... Obrigado

Kamal Jain
fonte