Magento 2: Create/Add Configurable Product Programmatically

This article shows how you can add Configurable Product programmatically in Magento 2.

I am using a standalone script for this purpose using Object Manager. You can use this code in your custom module as well by using Dependency Injection (DI) instead of Object Manager.

Initialize Object Manager and Set the Area code

The following things are done in the below code:

– Initialize the object manager.
– Set the area code as adminhtml as we are editing the product.
– Define the logger to log information about the delete process. Zend Logger is used.


<?php
error_reporting(1);
set_time_limit(0);
ini_set('memory_limit', '2048M');

use Magento\Framework\App\Bootstrap;
 
/**
 * If your external file is in root folder
 */
require __DIR__ . '/app/bootstrap.php';
 
/**
 * If your external file is NOT in root folder
 * Let's suppose, your file is inside a folder named 'xyz'
 *
 * And, let's suppose, your root directory path is
 * /var/www/html/magento2
 */
// $rootDirectoryPath = '/var/www/html/magento2';
// require $rootDirectoryPath . '/app/bootstrap.php';
 
$params = $_SERVER; 
$bootstrap = Bootstrap::create(BP, $params); 
$objectManager = $bootstrap->getObjectManager();

// Set Area Code
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode(\Magento\Framework\App\Area::AREA_ADMINHTML); // or \Magento\Framework\App\Area::AREA_FRONTEND, depending on your need

// Define Zend Logger
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/create-product.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);

Create Simple Products to be associated with the Configurable Product

First, we will create some simple products that we will associate to the configurable product that we create later.

In this example, we will use a single attribute named Color to create the configurable product. So, we create two simple products that will the option value of the color attribute. For example, first simple product can have color value as Black and the second product that we create can have color value as Blue.


$product = $objectManager->create('\Magento\Catalog\Model\Product');
$productRepository = $objectManager->get('Magento\Catalog\Api\ProductRepositoryInterface');

// $installer = $objectManager->create(\Magento\Catalog\Setup\CategorySetup::class);
// $attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default');
// OR
$attributeSetId = $product->getDefaultAttributeSetId();

$attributeLabel = 'Color';
$attributeCode = 'color';
$attribute = $product->getResource()->getAttribute($attributeCode);
$options = $attribute->getOptions();
array_shift($options); //remove the first option which is empty

/**
 * Note: 
 * 
 * If the product IDs defined below in the associatedProducts array
 * are present in the database, then those products will get updated
 * 
 * If the product IDs are not present in the database
 * then new products will be added with the IDs specified
 */
$associatedProductIds = [901, 902];

/**
 * Create/Update Associated Simple Products
 * 
 * We have defined 2 associated products above
 * So, we will only use the first 2 options of the attribute 
 * We will link the attribute option to the product
 */
foreach ($options as $key => $option) {
    if ($key == count($associatedProductIds)) {
        break;
    }

    $productId = $associatedProductIds[$key];
    $product = $objectManager->create(\Magento\Catalog\Model\Product::class); 
    $product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)
        ->setId($productId)
        ->setAttributeSetId($attributeSetId)
        ->setWebsiteIds([1])
        ->setName('Simple Product - ' . $option->getLabel())
        ->setSku('simple_' . $productId)
        ->setPrice($productId)
        ->setColor($option->getValue()) // Set the 'color' attribute option value
        ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE)
        ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
        ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]);

    $product = $productRepository->save($product);

    $msg = 'Created Simple Product. Product ID: ' . $product->getId();
    echo $msg . '<br />';
    $logger->info($msg);

    /** @var \Magento\CatalogInventory\Model\Stock\Item $stockItem */
    /* $stockItem = $objectManager->create(\Magento\CatalogInventory\Model\Stock\Item::class);
    $stockItem->load($productId, 'product_id');
    if (!$stockItem->getProductId()) {
        $stockItem->setProductId($productId);
    }
    $stockItem->setUseConfigManageStock(1);
    $stockItem->setQty(1000);
    $stockItem->setIsQtyDecimal(0);
    $stockItem->setIsInStock(1);
    $stockItem->save(); */

    $attributeValues[] = [
        'label' => $attributeLabel,
        'attribute_id' => $attribute->getId(),
        'value_index' => $option->getValue(),
    ];
}

Create Configurable Product and Assign Simple Products to it

Now, we create the configurable product and associate the above created simple products to it.


$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
$optionsFactory = $objectManager->create(\Magento\ConfigurableProduct\Helper\Product\Options\Factory::class);

$configurableAttributesData = [
    [
        'attribute_id' => $attribute->getId(),
        'code' => $attribute->getAttributeCode(),
        'label' => $attribute->getStoreLabel(),
        'position' => '0',
        'values' => $attributeValues,
    ],
];
$configurableOptions = $optionsFactory->create($configurableAttributesData);

$extensionConfigurableAttributes = $product->getExtensionAttributes();
$extensionConfigurableAttributes->setConfigurableProductOptions($configurableOptions);
$extensionConfigurableAttributes->setConfigurableProductLinks($associatedProductIds);

$product->setExtensionAttributes($extensionConfigurableAttributes);

/**
 * Create new configurable product
 * 
 * The simple products created above
 * will get associated with the newly created configurable product.
 */
$product->setTypeId(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE)
    //->setId(1)
    ->setAttributeSetId($attributeSetId)
    ->setWebsiteIds([1])
    ->setName('Test Configurable Product')
    ->setSku('test-configurable-2')
    ->setUrlKey('test-configurable-2')
    ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
    ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
    ->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]);

$product = $productRepository->save($product);

$msg = 'Created Configurable Product. Product ID: ' . $product->getId();
echo $msg . '<br />';
$logger->info($msg);

Full Code to Create Configurable Product

Here’s the full standalone code to create the configurable product:


<?php
error_reporting(1);
set_time_limit(0);
ini_set('memory_limit', '2048M');

use Magento\Framework\App\Bootstrap;
 
/**
 * If your external file is in root folder
 */
require __DIR__ . '/app/bootstrap.php';
 
/**
 * If your external file is NOT in root folder
 * Let's suppose, your file is inside a folder named 'xyz'
 *
 * And, let's suppose, your root directory path is
 * /var/www/html/magento2
 */
// $rootDirectoryPath = '/var/www/html/magento2';
// require $rootDirectoryPath . '/app/bootstrap.php';
 
$params = $_SERVER; 
$bootstrap = Bootstrap::create(BP, $params); 
$objectManager = $bootstrap->getObjectManager();

// Set Area Code
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode(\Magento\Framework\App\Area::AREA_ADMINHTML); // or \Magento\Framework\App\Area::AREA_FRONTEND, depending on your need

// Define Zend Logger
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/create-product.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);

$product = $objectManager->create('\Magento\Catalog\Model\Product');
$productRepository = $objectManager->get('Magento\Catalog\Api\ProductRepositoryInterface');

// $installer = $objectManager->create(\Magento\Catalog\Setup\CategorySetup::class);
// $attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default');
// OR
$attributeSetId = $product->getDefaultAttributeSetId();

$attributeLabel = 'Color';
$attributeCode = 'color';
$attribute = $product->getResource()->getAttribute($attributeCode);
$options = $attribute->getOptions();
array_shift($options); //remove the first option which is empty

/**
 * Note: 
 * 
 * If the product IDs defined below in the associatedProducts array
 * are present in the database, then those products will get updated
 * 
 * If the product IDs are not present in the database
 * then new products will be added with the IDs specified
 */
$associatedProductIds = [901, 902];

/**
 * Create/Update Associated Simple Products
 * 
 * We have defined 2 associated products above
 * So, we will only use the first 2 options of the attribute 
 * We will link the attribute option to the product
 */
foreach ($options as $key => $option) {
    if ($key == count($associatedProductIds)) {
        break;
    }

    $productId = $associatedProductIds[$key];
    $product = $objectManager->create(\Magento\Catalog\Model\Product::class); 
    $product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)
        ->setId($productId)
        ->setAttributeSetId($attributeSetId)
        ->setWebsiteIds([1])
        ->setName('Simple Product - ' . $option->getLabel())
        ->setSku('simple_' . $productId)
        ->setPrice($productId)
        ->setColor($option->getValue()) // Set the 'color' attribute option value
        ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE)
        ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
        ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]);

    $product = $productRepository->save($product);

    $msg = 'Created Simple Product. Product ID: ' . $product->getId();
    echo $msg . '<br />';
    $logger->info($msg);

    /** @var \Magento\CatalogInventory\Model\Stock\Item $stockItem */
    /* $stockItem = $objectManager->create(\Magento\CatalogInventory\Model\Stock\Item::class);
    $stockItem->load($productId, 'product_id');
    if (!$stockItem->getProductId()) {
        $stockItem->setProductId($productId);
    }
    $stockItem->setUseConfigManageStock(1);
    $stockItem->setQty(1000);
    $stockItem->setIsQtyDecimal(0);
    $stockItem->setIsInStock(1);
    $stockItem->save(); */

    $attributeValues[] = [
        'label' => $attributeLabel,
        'attribute_id' => $attribute->getId(),
        'value_index' => $option->getValue(),
    ];
}

$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
$optionsFactory = $objectManager->create(\Magento\ConfigurableProduct\Helper\Product\Options\Factory::class);

$configurableAttributesData = [
    [
        'attribute_id' => $attribute->getId(),
        'code' => $attribute->getAttributeCode(),
        'label' => $attribute->getStoreLabel(),
        'position' => '0',
        'values' => $attributeValues,
    ],
];
$configurableOptions = $optionsFactory->create($configurableAttributesData);

$extensionConfigurableAttributes = $product->getExtensionAttributes();
$extensionConfigurableAttributes->setConfigurableProductOptions($configurableOptions);
$extensionConfigurableAttributes->setConfigurableProductLinks($associatedProductIds);

$product->setExtensionAttributes($extensionConfigurableAttributes);

/**
 * Create new configurable product
 * 
 * The simple products created above
 * will get associated with the newly created configurable product.
 */
$product->setTypeId(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE)
    //->setId(1)
    ->setAttributeSetId($attributeSetId)
    ->setWebsiteIds([1])
    ->setName('Test Configurable Product')
    ->setSku('test-configurable-2')
    ->setUrlKey('test-configurable-2')
    ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
    ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
    ->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]);

$product = $productRepository->save($product);

$msg = 'Created Configurable Product. Product ID: ' . $product->getId();
echo $msg . '<br />';
$logger->info($msg);
?>

Reference: https://github.com/magento/magento2/blob/2.2.6/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php

Hope this helps. Thanks.