Magento2: cómo agregar un producto al carrito mediante programación cuando se activa checkout_cart_product_add_after

8

Considere que hay dos productos, es decir: el Producto A y el Producto B. El Producto B es un producto virtual que necesito agregar al carrito cuando se le agrega el Producto A.

Para hacerlo, estoy tratando de agregar el Producto B al carrito observando un evento checkout_cart_product_add_after. Una vez que se agrega el Producto A, estoy recuperando la cantidad de producto agregado para el Producto A y, en base a ello, estoy tratando de agregar el Producto B mediante programación. Para agregar el producto B, he escrito el siguiente código:

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

Sin embargo, intentar agregar un producto usando $this->_cart->addProduct()no funciona. ¿Alguien puede guiar cómo se puede hacer esto? ¿Hay algo que me falta?

Cualquier orientación será apreciada.

Diestro
fuente

Respuestas:

8

Para todos aquellos que podrían perder el día en el futuro, tenga en cuenta la respuesta a continuación que será útil para usted.

El código anterior para agregar producto al carrito funciona bien. Sin embargo, el problema es con la lógica. Lo explicaré a continuación.

En primer lugar, estaba tratando de agregar un producto en el evento checkout_cart_product_add_after. Este evento se activa cuando el producto se agrega al carrito.

Profundizando en el código, si va a ejecutar la función. El código para agregar el producto al carrito es:$this->_cart->addProduct($_product,$params);

Si marca la addProductfunción vendor/module-checkout/Model/Cart.php, verá que es la función la que está enviando el checkout_cart_product_add_afterevento.

Por lo tanto, en nuestro caso, el control volverá nuevamente al archivo de observación que nuevamente intentará agregar el producto al carrito. Se creará la recursión que se ejecutará hasta que se agote la cantidad de nuestro producto.

Una vez que la cantidad se agota, se detendrá. Ahora lo que tenemos que hacer es agregar una condición para detener esta recurrencia. La condición puede ser según su lógica.

Ahora, cada vez que se agrega un producto al carrito, $product->getId()se devolverá el último producto agregado. Puedes usar esto para poner condición.

Al final, mi código se parece a lo siguiente:

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

    }
}
Diestro
fuente
¿Qué pasa si el usuario actualiza el carrito? ¿Crees que esto todavía se disparará?
MagePsycho
2
Incluso desde Magento 2.1.0, este enfoque parece estar en desuso.
MagePsycho
@Dexter, ¿cómo agregar productos con la opción personalizada requerida al carrito?
Shell Suite
@MagePsycho cómo puedo saber qué funciona, ya que estás sugiriendo que va a ser obsoleto, quiero decir (estoy aprendiendo Magento 2) cómo sabes eso. Cualquier documentación o cualquier otra cosa que un desarrollador de Mage deba leer antes de personalizar cualquier funcionalidad.
inrsaurabh
$ item = $ observer-> getEvent () -> getData ('quote_item'); $ producto = $ observador-> getEvent () -> getData ('producto'); $ item = ($ item-> getParentItem ()? $ item-> getParentItem (): $ item); Si imprimo echo $ item-> getId (); Es nulo. No consigo nada aquí.
Dharmesh Hariyani
0

Hice otro formulario, para el cliente registrado y el carrito de invitados

<?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
fuente