Magento2 - Como adicionar um produto ao carrinho de forma programática quando o checkout_cart_product_add_after é acionado

8

Considere que existem dois produtos, ou seja: Produto A e Produto B. O Produto B é um produto viral que eu preciso adicionar ao carrinho quando o Produto A é adicionado a ele.

Para fazer isso, estou tentando adicionar o produto B ao carrinho, observando um evento checkout_cart_product_add_after. Depois que o Produto A é adicionado, estou recuperando a quantidade de produto adicionado ao Produto A e, com base nele, estou tentando adicionar o Produto B programaticamente. Para adicionar o produto B, escrevi o código abaixo:

<?php
namespace MyModule\Applicationcharges\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;

class AddCharges implements ObserverInterface
{
    protected $_productRepository;
    protected $_cart;

    public function __construct(\Magento\Catalog\Model\ProductRepository $productRepository, \Magento\Checkout\Model\Cart $cart){
        $this->_productRepository = $productRepository;
        $this->_cart = $cart;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $item=$observer->getEvent()->getData('quote_item');
        $product=$observer->getEvent()->getData('product');
        $item = ( $item->getParentItem() ? $item->getParentItem() : $item );
        $product->getQty();

        $params = array(
            'product' => 2056,
            'qty' => 1
        );

        $_product = $this->_productRepository->getById(2056);
        $this->_cart->addProduct($_product,$params);
        $this->_cart->save();
    }
}

No entanto, tentar adicionar produtos usando $this->_cart->addProduct()não funciona. Alguém pode, por favor, orientar como isso pode ser feito? Há alguma coisa que estou perdendo.

Qualquer orientação será apreciada.

Dexter
fonte

Respostas:

8

Para todos aqueles que possam perder seu dia no futuro, observe a resposta abaixo, que será útil para você.

O código acima para adicionar produto ao carrinho funciona bem. No entanto, o problema está na lógica. Vou explicar abaixo.

Antes de tudo, eu estava tentando adicionar um produto no evento checkout_cart_product_add_after. Este evento é acionado quando o produto é adicionado ao carrinho.

Mais informações sobre o código, se você precisar executar a função. O código para adicionar o produto ao carrinho é:$this->_cart->addProduct($_product,$params);

Se você marcar a addProductfunção vendor/module-checkout/Model/Cart.php, verá que é a função que está despachando o checkout_cart_product_add_afterevento.

Portanto, no nosso caso, o controle retornará novamente ao arquivo observador, que tentará adicionar novamente o produto ao carrinho. Será criada uma recursão que será executada até a quantidade de nosso produto esgotar.

Uma vez esgotada a quantidade, ela irá parar. Agora, o que precisamos fazer é adicionar uma condição para interromper essa recursão. A condição pode ser conforme sua lógica.

Agora, cada vez que um produto for adicionado ao carrinho, $product->getId()ele retornará o produto mais recente adicionado. Você pode usar isso para colocar a condição.

No final, meu código é algo como abaixo:

<?php
namespace MyModule\Applicationcharges\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;

class AddCharges implements ObserverInterface
{
    protected $_productRepository;
    protected $_cart;
    protected $formKey;

    public function __construct(\Magento\Catalog\Model\ProductRepository $productRepository, \Magento\Checkout\Model\Cart $cart, \Magento\Framework\Data\Form\FormKey $formKey){
        $this->_productRepository = $productRepository;
        $this->_cart = $cart;
        $this->formKey = $formKey;
    }
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $item = $observer->getEvent()->getData('quote_item');
        $product = $observer->getEvent()->getData('product');
        $item = ($item->getParentItem() ? $item->getParentItem() : $item);

        // Enter the id of the prouduct which are required to be added to avoid recurrssion
        if($product->getId() != 2056){
            $params = array(
                'product' => 2056,
                'qty' => $product->getQty()
            );
            $_product = $this->_productRepository->getById(2056);
            $this->_cart->addProduct($_product,$params);
            $this->_cart->save();
        }

    }
}
Dexter
fonte
E se o usuário atualizar o carrinho? Você acha que isso ainda será acionado?
precisa saber é o seguinte
2
Mesmo a partir do Magento 2.1.0, essa abordagem parece estar obsoleta.
precisa saber é o seguinte
@ Dexter como adicionar um produto com a opção personalizada necessária ao carrinho?
Shell Suite
@MagePsycho como posso saber o que funciona como você está sugerindo que será obsoleto, quero dizer (estou aprendendo Magento 2) como você sabe disso. Qualquer documentação ou qualquer outra coisa que um desenvolvedor Mage precise ler antes de personalizar qualquer funcionalidade.
Inrsaurabh 22/0318
$ item = $ observer-> getEvent () -> getData ('quote_item'); $ product = $ observer-> getEvent () -> getData ('produto'); $ item = ($ item-> getParentItem ()? $ item-> getParentItem (): $ item); Se eu imprimir echo $ item-> getId (); é nulo. não estou conseguindo nada aqui.
Dharmesh Hariyani
0

Fiz outro formulário, para cliente registrado e carrinho de convidado

<?php

namespace Ysa\Core\Controller\Api;

use Magento\Framework\App\Action\Action as Action;
use Magento\Framework\App\ResponseInterface;

class Cart extends Action
{
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Magento\Catalog\Model\Product $product,
        \Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface,
        \Magento\Store\Model\Store $store,
        \Magento\Checkout\Model\Session $session,
        \Magento\Catalog\Model\ProductFactory $productFactory,
        \Magento\Quote\Api\CartManagementInterface $quoteManagement
    ) {
        $this->resultPageFactory        = $resultPageFactory;
        $this->_cartRepositoryInterface = $cartRepositoryInterface;
        $this->_store                   = $store;
        $this->_session                 = $session;
        $this->_productFactory          = $productFactory;
        $this->_quoteManagement         = $quoteManagement;

        parent::__construct($context);
    }

    /**
     * @return ResponseInterface|\Magento\Framework\Controller\ResultInterface|void
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function execute()
    {
        $product_id = $this->getRequest()->getParam('product');
        $product = $this->_productFactory->create();
        $product->load($product_id);

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $customerSession = $objectManager->get('Magento\Customer\Model\Session');

        if ($customerSession->isLoggedIn()) {
            $customer = $customerSession->getCustomer();
            $quoteId = $this->_quoteManagement->createEmptyCartForCustomer($customer->getId());
            $quote = $this->_cartRepositoryInterface->get($quoteId);
            $quote->addProduct($product);
            $this->_cartRepositoryInterface->save($quote);
            $quote->collectTotals();
        } else {
            $quote = $this->_session->getQuote();
            $quote->setStore($this->_store);
            $quote->setCurrency();
            $quote->addProduct($product);
            $quote->save();
            $quote->collectTotals();
            $this->_cartRepositoryInterface->save($quote);
        }
    }
}


Israel Guido
fonte