0

I am facing some problems when trying to add to cart multiple configurable products in 1 single request

We have tuned product list page, to add the required form values for this kind of request (configurable child options, etc...) and this values are sent to a custom controller action

This is the controller code

<?php
namespace Vendor\Module\Controller\Add;

class Cart extends \Magento\Framework\App\Action\Action
{
    protected $_cart;
    protected $productRepository;
    protected $formKeyValidator;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Checkout\Model\Cart $cart,
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
        \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator
    ) {

        $this->_cart = $cart;
        $this->productRepository = $productRepository;
        $this->_formKeyValidator = $formKeyValidator;

        return parent::__construct($context);
    }

    public function execute()
    {
        if (!$this->_formKeyValidator->validate($this->getRequest())) {
            return $this->resultRedirectFactory->create()->setPath('*/*/');
        }

        $qtys       = $this->getRequest()->getParam('qty');
        $childIds   = $this->getRequest()->getParam('child_ids');

        $add = array();
        foreach ($qtys as $parentId => $array) {
            if (is_array($array)) {
                foreach ($array as $attributeId => $child) {
                    foreach ($child as $childId => $value) {
                        if ($value != 0) {
                            $add[$parentId][$attributeId][$childId] = $value;
                        }
                    }
                }
            } else {
                // simple products?
                // @todo
            }
        }

        foreach ($add as $productId => $data) {
            $_product = $this->productRepository->getById($productId);

            foreach ($data as $attributeId => $child) {
                foreach ($child as $childId => $qty) {
                    $options = array(
                        $attributeId => $childId,
                    );

                    $params = array(
                        'form_key' => $this->getRequest()->getParam('form_key'),
                        'product' => $productId,
                        'super_attribute' => $options,
                        'qty' => $qty,
                        'selected_configurable_option' => $childIds[$productId][$attributeId][$childId],
                    );
                    $this->_cart->addProduct($_product, $params);
                }
            }
        }
        $this->_cart->save();
        return $this->resultRedirectFactory->create()->setPath('checkout/cart');
    }
}

This are the results I am getting

  • when adding different children of same configurable product only the first is being added to cart (with qtys of others being added to that first child)
  • when adding different configurable products (with any children) product prices are displayed correctly only in the first configurable product... the others show price 0€

Assuming the data in both $qtys & $childIds arrays are correct (I have validated them against data sent from a configurable product view add to cart request, and they seem ok), can you lead me to the error in the controller code, or any missing code required to be added?

2

As reported here https://magento.stackexchange.com/a/110666/3566, problem was we have to create each time new product object

I have tried different ways, trying to avoid using $this->_objectManager

Using \Magento\Catalog\Model\ProductFactory was the only way to make that work

So, apart from adding the new dependency in constructor, with this code changes...

    foreach ($add as $productId => $data) {
        foreach ($data as $attributeId => $child) {
            foreach ($child as $childId => $qty) {
                // @see https://magento.stackexchange.com/a/110666/3566 -> reload product
                $_product = $this->productFactory->create()->setStoreId($storeId)->load($productId);
                $options = array(
                    $attributeId => $childId,
                );

                $params = array(
                    'form_key' => $this->getRequest()->getParam('form_key'),
                    'product' => $productId,
                    'super_attribute' => $options,
                    'qty' => $qty,
                    'selected_configurable_option' => $childIds[$productId][$attributeId][$childId],
                );

                $this->_cart->addProduct($_product, $params);
                $this->_cart->save();
            }
        }
    }

All products are being added to cart correctly, although I have seen some pricing issues (only first configurable product has the right price & the others print 0€), but that's another story

| improve this answer | |
  • Thank you! I was using the $productRepository variable that was already a dependency and just could not figure out why it wasn't working. Adding the new dependency for the $productFactory and using the code to create a new product each time solved my issue which was that all simple products of the same configurable product were not showing separately in the cart, even though the quote data in the database was correct. – BVBAccelerate Oct 13 at 18:31
2

You need to keep cart save logic outside the foreach loop, So your price issue will be resolved,

    foreach ($add as $productId => $data) {
        foreach ($data as $attributeId => $child) {
            foreach ($child as $childId => $qty) {
                // @see https://magento.stackexchange.com/a/110666/3566 -> reload product
                $_product = $this->productFactory->create()->setStoreId($storeId)->load($productId);
                $options = array(
                    $attributeId => $childId,
                );

                $params = array(
                    'form_key' => $this->getRequest()->getParam('form_key'),
                    'product' => $productId,
                    'super_attribute' => $options,
                    'qty' => $qty,
                    'selected_configurable_option' => $childIds[$productId][$attributeId][$childId],
                );

                $this->_cart->addProduct($_product, $params);
            }
        }
    }
  $this->_cart->save();
| improve this answer | |
  • That worked! Thanks... Do you know why this happens? – Raul Sanchez Jul 6 '18 at 16:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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