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();
Was it helpful?

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();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top