How to Add Multiple Products in Magento 2 Programmatically

Add multiple products in Magento 2 programmatically to save time, eliminate manual entry, and keep your catalog clean and scalable.

Managing products efficiently is a crucial part of any Magento 2 store. Whether you’re launching a new catalog or integrating products from a third-party system, the ability to add multiple products programmatically can save a tremendous amount of time and effort.

In this blog post, we’ll explore how you can programmatically add both Simple and Configurable products simultaneously in Magento 2. This is especially useful for developers and store administrators looking to automate product creation through scripts or integrations.

<?php

namespace Vendor\Module\Controller\BulkToCart;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Data\Form\FormKey;
use Magento\Checkout\Model\Cart;
use Magento\Catalog\Model\ProductFactory;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable;
use Magento\Framework\Message\ManagerInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\DataObject;
use Psr\Log\LoggerInterface;

class Index extends Action
{
    protected $formKey;
    protected $cart;
    protected $productFactory;
    protected $resultJsonFactory;
    protected $productRepository;
    protected $logger;

    public function __construct(
        Context $context,
        FormKey $formKey,
        Cart $cart,
        ProductFactory $productFactory,
        JsonFactory $resultJsonFactory,
        ProductRepositoryInterface $productRepository,
        LoggerInterface $logger
    ) {
        $this->formKey = $formKey;
        $this->cart = $cart;
        $this->productFactory = $productFactory;
        $this->resultJsonFactory = $resultJsonFactory;
        $this->productRepository = $productRepository;
        $this->logger = $logger;
        parent::__construct($context);
    }

    public function execute()
    {
        $result = $this->resultJsonFactory->create();
        $content = json_decode($this->getRequest()->getContent(), true);

        if (!isset($content['items'])) {
            return $result->setData(['success' => false, 'message' => 'No items found']);
        }

        foreach ($content['items'] as $key => $item) {
            try {
                $product = $this->productFactory->create()->load($item['product_id']);
                if (!$product->getId()) {
                     $this->logger->info("Product ID {$item['product_id']} not found.");
                    continue;
                }

                 $this->logger->info("Attempting to add Product ID: {$product->getId()}, itemSku: {$item['sku']}, SKU: {$product->getSku()}, Type: {$product->getTypeId()}");

                if (!$product->isSaleable()) {
                     $this->logger->info("Product ID {$product->getId()} is not saleable.");
                    continue;
                }

                if ($product->getTypeId() == 'configurable') {
                    // Add Configurable Products
                    $childId = $this->getChildProduct($item['sku']);
                    $parent = $this->productRepository->getById($product->getId());
                    $child = $this->productRepository->getById($childId);
                    unset($options);
                    $options = [];
                    $productAttributeOptions = $parent->getTypeInstance(true)->getConfigurableAttributesAsArray($parent);

                    foreach ($productAttributeOptions as $option) {
                        $attributeId = $option['attribute_id'];
                        $attributeCode = $option['attribute_code'];
                        $attributeValue = $child->getData($attributeCode);
                        if ($attributeValue !== null) {
                            $options[$attributeId] = $attributeValue;
                        }
                    }

                    $params = [
                        'form_key' => $this->formKey->getFormKey(),
                        'product' => $parent->getId(),
                        'qty' => $item['qty'],
                        'super_attribute' => $options,
                        'options' => [
                            'child_id' => $child->getId(),
                        ]
                    ];
                     $this->logger->info('Configurable Product Params: ' . json_encode($params));
                } else {
                    // Add Simple Products
                    $params = [
                        'form_key' => $this->formKey->getFormKey(),
                        'product' => $product->getId(),
                        'qty' => $item['qty'] ?? 1

                    ];
                     $this->logger->info('Simple Product Params: ' . json_encode($params));
                }
                $buyRequest = new DataObject($params);
                $this->cart->addProduct($product, $buyRequest);
                $this->cart->save();
                $this->logger->info('Add Products successfully---');
            } catch (\Exception $e) {
                 return $result->setData(['success' => false, 'message' => $e->getMessage()]);
            }
        }
    }

    public function getChildProduct($sku)
    {
        $product = $this->productRepository->get($sku);
        return $product->getId();
    }
}

Conclusion

Adding multiple products programmatically in Magento 2 — especially a mix of simple and configurable products — is a powerful way to manage your catalog efficiently. Whether you’re working on a migration, a custom integration, or batch product creation, automating the process improves productivity and scalability.

Now that you understand the strategy, you can implement it confidently using Magento 2’s object-oriented architecture and dependency injection system. In the next post, we’ll walk you through the actual PHP code to create these products step-by-step.

Retrieve Simple Product from Configurable Product on Swatch in Magento 2

Leave a Reply

Your email address will not be published. Required fields are marked *