Magento 2: Create/Add Product Programmatically [Simple & Virtual Product with Image, Category & Custom Option]

This article shows how you can add Simple & Virtual products programmatically in Magento 2.

This article also shows how you can:

– add images to the product
– assign the product to different categories
– add custom options to the product

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 Virutal Product

One difference between a virtual product and a simple product is that the virtual product does not have weight, whereas the simple product has weight.

Here’s the code to create a virtual product:


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

// Get the default attribute set id
$attributeSetId = $product->getDefaultAttributeSetId();

$sku = $urlKey = 'test-product-virtual';

$product->setSku($sku); // sku of the product
$product->setName('My Test Product'); // name of the product
$product->setUrlKey($urlKey); // url key of the product
$product->setAttributeSetId($attributeSetId); // attribute set id
$product->setStatus(1); // enabled = 1, disabled = 0
$product->setVisibility(4); // visibilty of product, 1 = Not Visible Individually, 2 = Catalog, 3 = Search, 4 = Catalog, Search
$product->setTaxClassId(0); // Tax class id, 0 = None, 2 = Taxable Goods, etc.
$product->setTypeId('virtual'); // type of product (simple/virtual/downloadable/configurable)
//$product->setProductHasWeight(1); // 1 = simple product, 0 = virtual product
//$product->setWeight(5); // weight of product
$product->setPrice(100); // price of the product
$product->setWebsiteIds(array(1)); // Assign product to Websites
$product->setCategoryIds(array(10, 18, 38)); // Assign product to categories
$product->setStockData(
    array(
        'use_config_manage_stock' => 0,
        'manage_stock' => 1,
        'is_in_stock' => 1,
        'qty' => 999999
    )
);
$product->save();

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

Create Simple Product

We have to assign weight to the product in order to create a simple product. If we don’t assign weight to the product then that product will be created as a virtual product.

Here’s the code to create a simple product:


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

// Get the default attribute set id
$attributeSetId = $product->getDefaultAttributeSetId();

$sku = $urlKey = 'test-product-simple';

$product->setSku($sku); // sku of the product
$product->setName('My Test Product'); // name of the product
$product->setUrlKey($urlKey); // url key of the product
$product->setAttributeSetId($attributeSetId); // attribute set id
$product->setStatus(1); // enabled = 1, disabled = 0
$product->setVisibility(4); // visibilty of product, 1 = Not Visible Individually, 2 = Catalog, 3 = Search, 4 = Catalog, Search
$product->setTaxClassId(0); // Tax class id, 0 = None, 2 = Taxable Goods, etc.
$product->setTypeId('simple'); // type of product (simple/virtual/downloadable/configurable)
$product->setProductHasWeight(1); // 1 = simple product, 0 = virtual product
$product->setWeight(5); // weight of product
$product->setPrice(100); // price of the product
$product->setWebsiteIds(array(1)); // Assign product to Websites
$product->setCategoryIds(array(10, 18, 38)); // Assign product to categories
$product->setStockData(
    array(
        'use_config_manage_stock' => 0,
        'manage_stock' => 1,
        'is_in_stock' => 1,
        'qty' => 999999
    )
);
$product->save();

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

Add images to the product

Please note that for this example:

– I am using a standalone script using Object Manager.
– My script is in the root folder of my Magento shop.
– And, I have kept the product images inside pub/media/product_images folder of my Magento site.


/**
 * Add image to media gallery
 *
 * @param string        $file              file path of image in file system
 * @param string|array  $mediaAttribute    code of attribute with type 'media_image',
 *                                          leave blank if image should be only in gallery
 * @param boolean       $move              if true, it will move source file
 * @param boolean       $exclude           mark image as disabled in product page view
 * @return \Magento\Catalog\Model\Product
 */
// addImageToMediaGallery($file, $mediaAttribute = null, $move = false, $exclude = true)

/**
 * Add image to the product
 * 
 * Note that, for this example, I am using a standalone script using Object Manager
 * My script is in the root folder of my Magento shop
 * And, I have kept the product images inside pub/media/product_images folder of my Magento site
 */
$images = [
    BP . '/pub/media/product_images/image_1.png', 
    BP . '/pub/media/product_images/image_2.png', 
];

foreach ($images as $image) {
    $product->addImageToMediaGallery($image, array('image', 'small_image', 'thumbnail'), false, false);
    $product->save();
}

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

Add custom options to the product

I have written an article before on adding custom options to the product. Here’s the link to it: Magento 2: Add / Delete / View Custom Options of Product Programmatically

In the below code, I have added two custom options: Color and Size with some values to them.

Here’s the code to add custom options to a simple product:


$productId = $product->getId();
$productRepository = $objectManager->get('Magento\Catalog\Api\ProductRepositoryInterface');
$prod = $productRepository->getById($productId);

$options = [
                [
                    'title' => 'Color',
                    'type' => 'drop_down',
                    'is_required' => 1,
                    'sort_order' => 0,
                    'values' => [
                        [
                            'title' => 'Blue',
                            'price' => 10.50,
                            'price_type' => 'fixed',
                            'sku' => '',
                            'sort_order' => 0,
                        ],
                        [
                            'title' => 'Black',
                            'price' => 0,
                            'price_type' => 'percent',
                            'sku' => 'test-product-sku',
                            'sort_order' => 0,
                        ]
                    ]
                ],
                [
                    'title' => 'Size',
                    'type' => 'drop_down',
                    'is_required' => 1,
                    'sort_order' => 0,
                    'values' => [
                        [
                            'title' => 'S',
                            'price' => 0,
                            'price_type' => 'fixed',
                            'sku' => '',
                            'sort_order' => 0,
                        ],
                        [
                            'title' => 'M',
                            'price' => 0,
                            'price_type' => 'fixed',
                            'sku' => '',
                            'sort_order' => 0,
                        ],
                        [
                            'title' => 'L',
                            'price' => 0,
                            'price_type' => 'fixed',
                            'sku' => '',
                            'sort_order' => 0,
                        ]
                    ]
                ]
            ];

// $prod->setHasOptions(1);
// $prod->setCanSaveCustomOptions(true);

foreach ($options as $arrayOption) {
    $customOption = $objectManager->create('\Magento\Catalog\Model\Product\Option')
                        ->setProductId($productId)
                        ->setStoreId($prod->getStoreId())
                        ->addData($arrayOption);

    $customOption->save();
    $prod->addOption($customOption);
}

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

Hope this helps. Thanks.