Magento 2: Add / Delete / View Custom Options of Product Programmatically

Custom options on Magento products are designed to make simple products function like a configurable product with different choosing options like color, size, etc. before purchasing the product.

In this tutorial, I present the code to create/add, view and delete custom options of a simple product 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);
 
$obj = $bootstrap->getObjectManager();
 
// Set area code
$state = $obj->get('Magento\Framework\App\State');
$state->setAreaCode('adminhtml');

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

Display a Product’s Custom Options and their values of the custom options


$productId = 2057;
$productRepository = $obj->get('Magento\Catalog\Api\ProductRepositoryInterface');
$product = $productRepository->getById($productId);

$customOptions = $product->getOptions();
 
foreach ($product->getOptions() as $option) {
    echo '<pre>'; 
    echo '=========== OPTION =============<br />';
    print_r($option->getData());

    foreach ($option->getValues() as $value) {
        echo '<pre>'; 
        echo '=========== VALUE =============<br />';
        print_r($value->getData());
    }
}

Sample Output:


=========== OPTION =============
Array
(
    [option_id] => 1
    [product_id] => 2057
    [type] => drop_down
    [is_require] => 1
    [sku] => 
    [max_characters] => 0
    [file_extension] => 
    [image_size_x] => 0
    [image_size_y] => 0
    [sort_order] => 1
    [default_title] => Color
    [store_title] => 
    [title] => Color
    [default_price] => 
    [default_price_type] => 
    [store_price] => 
    [store_price_type] => 
    [price] => 
    [price_type] => 
)
=========== VALUE =============
Array
(
    [option_type_id] => 1
    [option_id] => 1
    [sku] => 
    [sort_order] => 1
    [default_title] => Red
    [store_title] => 
    [title] => Red
    [default_price] => 10.0000
    [default_price_type] => fixed
    [store_price] => 
    [store_price_type] => 
    [price] => 10.0000
    [price_type] => fixed
)
=========== VALUE =============
Array
(
    [option_type_id] => 2
    [option_id] => 1
    [sku] => 
    [sort_order] => 2
    [default_title] => Green
    [store_title] => 
    [title] => Green
    [default_price] => 12.0000
    [default_price_type] => fixed
    [store_price] => 
    [store_price_type] => 
    [price] => 12.0000
    [price_type] => fixed
)

Add Custom Options to a Product

In the below code, we add two custom options to a particular product. The two custom options that we add are “Color” and “Size“. We also add some values to those custom options.


$productId = 2056;
$productRepository = $obj->get('Magento\Catalog\Api\ProductRepositoryInterface');
$product = $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,
                        ]
                    ]
                ]
            ];

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

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

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

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

Delete Custom Options of a Product


$productId = 2057;
$productRepository = $obj->get('Magento\Catalog\Api\ProductRepositoryInterface');
$product = $productRepository->getById($productId);

if (!empty($product->getOptions())) {
    foreach ($product->getOptions() as $option) {
        $option->delete();
        $msg = 'Product ID: ' . $product->getId() . 
             ' || Deleted Option ID: ' . $option->getId() . 
             ', Option Title: ' . $option->getTitle();
    
        echo $msg . '<br />';    
        $logger->info($msg);
    }
    
    $product->setHasOptions(0)->save();
} else {
    $msg = 'Product ID: ' . $product->getId() . 
    ' || No custom option.'; 

    echo $msg . '<br />';    
    $logger->info($msg);
}

Sample output in the log file

As we have defined above, the log message is saved in the file: var/log/delete-product-custom-options.log


2018-11-08T10:00:24+00:00 INFO (6): Product ID: 2057 || Deleted Option ID: 2, Option Title: Color
2018-11-08T10:00:24+00:00 INFO (6): Product ID: 2057 || Deleted Option ID: 3, Option Title: Size

Delete Custom Options of ALL Products

In the above code, we saw how to load a particular product and delete the custom options of that particular product.

In this example code, we see how to loop through all the products in the store and delete custom options of all the products.


$collectionRepository = $obj->get('Magento\Catalog\Model\ResourceModel\Product\CollectionFactory');
$collection = $collectionRepository->create();
$collection->addAttributeToSelect('*');

foreach ($collection as $prod) {
    $productId = $prod->getId();
    $productRepository = $obj->get('Magento\Catalog\Api\ProductRepositoryInterface');
    $product = $productRepository->getById($productId);

    if (!empty($product->getOptions())) {
        foreach ($product->getOptions() as $option) {
            $option->delete();
            $msg = 'Product ID: ' . $product->getId() . 
                ' || Deleted Option ID: ' . $option->getId() . 
                ', Option Title: ' . $option->getTitle();
        
            echo $msg . '<br />';    
            $logger->info($msg);
        }
        
        $product->setHasOptions(0)->save();
    } else {
        $msg = 'Product ID: ' . $product->getId() . 
        ' || No custom option.'; 

        echo $msg . '<br />';    
        $logger->info($msg);
    }
}

Hope this helps. Thanks.