Magento2 - How to add a product into cart programatically when checkout_cart_product_add_after is fired

magento.stackexchange https://magento.stackexchange.com/questions/319600

Question

Consider there are two product ie: Product A and Product B. Product B is a virual product which i need to add to cart when Product A is added to it.

To do so, I am trying to add Product B to cart by observing an event checkout_cart_product_add_after. Once Product A is added, i am retrieving the quantity of product added for Product A and based on it I am trying to add Product B programatically. To add product B, I have written below code:

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

However, trying to add product using $this->_cart->addProduct() doesn't work. Can anyone please guide how this can be done? Is there anything which I am missing.

Any guidance will be appreciated.

Était-ce utile?

La solution

For all those who might waste their day in future, please note below answer which will be helpful to you.

The above code to add product into cart works fine. However the problem is with the logic. I will explain it below.

First of all I was trying to add a product on event checkout_cart_product_add_after. This event is fired when product is added to the cart.

Further digging into code, if you goto execute function. The code for adding the product into cart is: $this->_cart->addProduct($_product,$params);

If you check addProduct function in vendor/module-checkout/Model/Cart.php you will see it is the function which is dispatching checkout_cart_product_add_after event.

Hence, in our case the control will again return to the observer file which will again try to add product into cart. Recursion will be created which will run until the quantity of our product exhaust.

Once the quantity is exhausted it will stop. Now what we need to do is, add a condition to stop this recursion. The condition can be as per your logic.

Now each time a product is added to cart $product->getId() will return the latest product added. You can use this to put condition.

In the end my code look something like below:

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

    }
}

Autres conseils

I made another form, for logged customer and guest cart

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


For those who are searching this for Magento 2 try this module https://github.com/gaiterjones/magento2-module-buyxgety

Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top