Create a bundle product programmatically - Magento 2
-
14-04-2021 - |
Question
I am trying to create a bundle product with Magento 2. But somehow its not linking simple products with the bundle product (i.e. its not saving
bundle options & data, also linking same with product). Can anyone have a look at below code snippet and let me know what I'm doing wrong?
//handle sub-items or sizes
foreach($item->Size as $size){
//$item_name = $name."-".$size->SizeLabel;
$sku = strtolower($size->SizeLabel)."_".$pID;
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // instance of object manager
$product = $objectManager->create('\Magento\Catalog\Model\Product');
$product->setSku($sku); // Set your sku here
$product->setName($size->SizeLabel); // Name of Product
$product->setStoreId(1);
$product->setAttributeSetId(4);
$product->setStatus(1); // Status on product enabled/ disabled 1/0
$product->setWeight($size->Weight); // weight of product
$product->setVisibility(1); // visibilty of product (catalog / search / catalog, search / Not visible individually)
$product->setTaxClassId(0); // Tax class id
$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE); // type of product (simple/virtual/downloadable/configurable)
$product->setPrice($size->UnitPrice); // price of product
$product->setWebsiteIds(array(1)); // set website Id
$product->setStockData(array('use_config_manage_stock' => 0, 'manage_stock' => 1, 'is_in_stock' => 1, 'qty' => 9999));
$product->save();
$options[] = array(
'product_id' => $product->getId(), //if of a product in selection
'delete' => '',
'selection_price_value' => 0,
'selection_price_type' => 0,
'selection_qty' => 1,
'selection_can_change_qty' => 0,
'position' => 0,
'is_default' => 0,
'name' => $size->SizeLabel,
'sku' => $sku,
'price' => $size->UnitPrice
);
}
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // instance of object manager
$product = $objectManager->create('\Magento\Catalog\Model\Product');
$product->setSku('sku'); // Set your sku here
//Map product with category
$category = $this->_saveCategory($item->WebCategory);
if ($category->getId())
{
$product->setCategoryIds([$category->getId()]);
}
$product->setName($name); // Name of Product
$product->setStoreId(1);
$product->setAttributeSetId(4);
$product->setStatus(1); // Status on product enabled/ disabled 1/0
$product->setWeight($item->Weight); // weight of product
$product->setVisibility(4); // visibilty of product (catalog / search / catalog, search / Not visible individually)
$product->setTaxClassId(0); // Tax class id
$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE); // type of product (simple/virtual/downloadable/configurable)
$product->setPrice($item->UnitPrice); // price of product
$product->setDescription($item->WebDescription); // description of product
$product->setWebsiteIds(array(1)); // set website Id
$product->setStockData(array('use_config_manage_stock' => 1, 'manage_stock' => 1, 'is_in_stock' => 1, 'qty' => 9999));
$bundleOptions = array(
'0' => array(//option id (0, 1, 2, etc)
'title' => 'Size', //option title
'option_id' => '',
'delete' => '',
'type' => 'radio', //option type
'required' => '1', //is option required
'position' => '1' //option position
)
);
$bundleSelections = array(
'0' => array(//option ID
$options
)
);
$this->registry->register('product', $product);
$this->registry->register('productCheck', $product);
$this->registry->register('current_product', $product);
$product->setCanSaveConfigurableAttributes(false);
$product->setCanSaveCustomOptions(true);
$product->setCanSaveBundleSelections(true);
$product->setAffectBundleProductSelections(true);
// Set the Bundle Options & Selection Data
$product->setBundleOptionsData($bundleOptions);
$product->setBundleSelectionsData($bundleSelections);
$product->save();
Solution
You code should like:
/** @var $objectManager \Magento\TestFramework\ObjectManager */
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // instance of object manager
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
$productRepository = $objectManager->create(Magento\Catalog\Api\ProductRepositoryInterface::class);
//handle sub-items or sizes
foreach($item->Size as $size){
//$item_name = $name."-".$size->SizeLabel;
$sku = strtolower($size->SizeLabel) . "_" . $pID;
/** @var \Magento\Catalog\Api\Data\ProductInterface $product */
$product = $objectManager->create(\Magento\Catalog\Api\Data\ProductInterface::class);
$product->setSku($sku); // Set your sku here
$product->setName($size->SizeLabel); // Name of Product
$product->setAttributeSetId(4);
$product->setStatus(1); // Status on product enabled/ disabled 1/0
$product->setWeight($size->Weight); // weight of product
$product->setVisibility(1); // visibilty of product (catalog / search / catalog, search / Not visible individually)
$product->setCustomAttribute('tax_class_id', 0);
$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE); // type of product (simple/virtual/downloadable/configurable)
$product->setPrice($size->UnitPrice); // price of product
/** @var \Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem */
$stockItem = $objectManager->create(\Magento\CatalogInventory\Api\Data\StockItemInterface::class);
$stockItem->setUseConfigManageStock(false);
$stockItem->setManageStock(true);
$stockItem->getIsInStock(true);
$stockItem->setQty(9999);
$productExtension->setStockItem($stockItem);
/** @var \Magento\Catalog\Api\Data\ProductExtensionInterface $productExtension */
$productExtension = $objectManager->create(\Magento\Catalog\Api\Data\ProductExtensionInterface::class);
$product->setExtensionAttributes($productExtension);
$product = $productRepository->save($product, true);
/** @var \Magento\Bundle\Api\Data\LinkInterface $link */
$link = $objectManager->create(\Magento\Bundle\Api\Data\LinkInterface::class);
$link->setPosition(0);
$link->setSku($product->getSku());
$link->setIsDefault(false);
$link->getQty(1);
$link->setPrice($size->UnitPrice);
$link->setPriceType(\Magento\Bundle\Api\Data\LinkInterface::PRICE_TYPE_FIXED);
$links[] = $link;
}
/** @var \Magento\Catalog\Api\Data\ProductInterface $product */
$product = $objectManager->create(\Magento\Catalog\Api\Data\ProductInterface::class);
$product->setSku('sku'); // Set your sku here
//Map product with category
//$category = $this->_saveCategory($item->WebCategory);
//if ($category->getId())
//{
// $product->setCategoryIds([$category->getId()]);
//}
$product->setName($name); // Name of Product
$product->setAttributeSetId(4);
$product->setStatus(1); // Status on product enabled/ disabled 1/0
$product->setWeight($item->Weight); // weight of product
$product->setVisibility(4); // visibilty of product (catalog / search / catalog, search / Not visible individually)
$product->setCustomAttribute('tax_class_id', 0);; // Tax class id
$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE); // type of product (simple/virtual/downloadable/configurable)
$product->setPrice($item->UnitPrice); // price of product
$product->setCustomAttribute('description', $item->WebDescription); // description of product
/** @var \Magento\Catalog\Api\Data\ProductExtensionInterface $productExtension */
$productExtension = $objectManager->create(\Magento\Catalog\Api\Data\ProductExtensionInterface::class);
/** @var \Magento\Bundle\Api\Data\OptionInterface $option */
$option = $objectManager->create(\Magento\Bundle\Api\Data\OptionInterface::class);
$option->setTitle('Size');
$option->setType('radio');
$option->setRequired(true);
$option->setPosition(1);
$option->setProductLinks($links);
$productExtension->setBundleOptions([$option]);
/** @var \Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem */
$stockItem = $objectManager->create(\Magento\CatalogInventory\Api\Data\StockItemInterface::class);
$stockItem->setUseConfigManageStock(false);
$stockItem->setManageStock(true);
$stockItem->getIsInStock(true);
$stockItem->setQty(9999);
$productExtension->setStockItem($stockItem);
$product->setExtensionAttributes($productExtension);
$productRepository->save($product, true);
OTHER TIPS
Magento2 programmatically adding a custom option
I propose to look at this post - which provides much easier answer and first of all working one. Look at /dev/tests/integration/testsuite/Magento/Bundle/_files/product.php
There is a script adding bundle product with one option and one linked product.
If you facing Fatal error:
Cannot instantiate interface Magento\Catalog\Api\Data\ProductExtensionInterface
issue then please try following solution.
I have tried it personally and it worked.
Instead of
$productExtension = $objectManager->create(\Magento\Catalog\Api\Data\ProductExtensionInterface::class);
Replace it with
use Magento\Catalog\Api\Data\ProductExtension;
$productExtension = $objectManager->create(ProductExtension::class);
After that if you facing issue of "Price view" not set for bundle product then use below code.
$product->setPriceView(1);
I have found working solution.
Reference link : https://www.rohanhapani.com/how-to-create-bundle-product-programmatically-in-magento-2/
You need to create bundleproduct.php file at Magento 2 root folder and then, add this below code :
<?php
use Magento\Framework\App\Bootstrap;
require __DIR__ . '/app/bootstrap.php';
$params = $_SERVER;
$bootstrap = Bootstrap::create(BP, $params);
$objectManager = $bootstrap->getObjectManager();
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode('frontend');
$product = $objectManager->create('Magento\Catalog\Model\Product');
try {
$product->setName('Bundle Product');
$product->setTypeId('bundle');
$product->setAttributeSetId(11);
$product->setSku('bundle-product');
$product->setWebsiteIds([1]);
$product->setVisibility(4);
$product->setImage('/bundle/test1.jpg');
$product->setSmallImage('/bundle/test1.jpg');
$product->setThumbnail('/bundle/test1.jpg');
$product->setPriceType(0);
$product->setPriceView(0);
$product->save();
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($product->getId());
// Set bundle product items
$product->setBundleOptionsData(
[
[
'title' => 'Bundle Product Items 1',
'default_title' => 'Bundle Product Items 1',
'type' => 'select',
'required' => 1,
'delete' => '',
],
[
'title' => 'Bundle Product Items 2',
'default_title' => 'Bundle Product Items 2',
'type' => 'select',
'required' => 1,
'delete' => '',
]
]
)->setBundleSelectionsData(
[
[
['product_id' => 1, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''],
['product_id' => 3, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''],
],
[
['product_id' => 2, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''],
['product_id' => 4, 'selection_qty' => 1, 'selection_can_change_qty' => 1, 'delete' => ''],
],
]
);
if ($product->getBundleOptionsData())
{
$options = [];
foreach ($product->getBundleOptionsData() as $key => $optionData)
{
if (!(bool) $optionData['delete'])
{
$option = $objectManager->create('Magento\Bundle\Api\Data\OptionInterface');
$option->setData($optionData);
$option->setSku($product->getSku());
$option->setOptionId(null);
$links = [];
$bundleLinks = $product->getBundleSelectionsData();
if (!empty($bundleLinks[$key]))
{
foreach ($bundleLinks[$key] as $linkData)
{
if (!(bool) $linkData['delete'])
{
/** @var \Magento\Bundle\Api\Data\LinkInterface$link */
$link = $objectManager->create('Magento\Bundle\Api\Data\LinkInterface');
$link->setData($linkData);
$linkProduct = $objectManager->get('\Magento\Catalog\Api\ProductRepositoryInterface')->getById($linkData['product_id']);
$link->setSku($linkProduct->getSku());
$link->setQty($linkData['selection_qty']);
if (isset($linkData['selection_can_change_qty']))
{
$link->setCanChangeQuantity($linkData['selection_can_change_qty']);
}
$links[] = $link;
}
}
$option->setProductLinks($links);
$options[] = $option;
}
}
}
$extension = $product->getExtensionAttributes();
$extension->setBundleProductOptions($options);
$product->setExtensionAttributes($extension);
}
$product->save();
if ($product->getId())
{
echo "Product Created Successfully";
}
} catch (\Exception $e) {
echo $e->getMessage();
}