10

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.

3 Answers 3

10

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

    }
}
6
  • What if user updates the cart? Do you think this will still triggered?
    – MagePsycho
    Commented Aug 2, 2016 at 10:31
  • 2
    Even from Magento 2.1.0 this approach seems to be deprecated.
    – MagePsycho
    Commented Aug 2, 2016 at 11:21
  • @Dexter how to add product with required custom option to the cart? Commented May 2, 2017 at 8:17
  • @MagePsycho how i can know that which function as you are suggesting that it going to be deprecated, i mean( i am learning Magento 2 ) how you know that. Any documentation or anything else a Mage developer must read before we customize any functionality.
    – inrsaurabh
    Commented Mar 22, 2018 at 6:41
  • $item = $observer->getEvent()->getData('quote_item'); $product = $observer->getEvent()->getData('product'); $item = ($item->getParentItem() ? $item->getParentItem() : $item); If i print echo $item->getId(); it is null. i am not getting anything here. Commented Mar 31, 2018 at 5:28
0

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


0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.