Magento2 programmatically adding a custom option

The question:

I’m trying to programmatically add a custom option to a product, there are no errors being returned, but the custom option doesn’t get added. I’ve tried a few methods to achieve this, without much luck.

Here’s my code as it stands:

$product = $this->objectManager->get('MagentoCatalogModelProduct')->load($productID);

$productOption = $this->objectManager->get('MagentoCatalogModelProductOption');
    'title' => 'Text',
    'price' => '1.00',
    'max_characters' => '50',
    'price_type' => 'fixed',
    'sort_order' => '1'

Any ideas what I’m doing wrong?


I’ve now tried a different method:

$product = $this->objectManager->get('MagentoCatalogModelProduct')->load($productID);
    'title' => 'Text',
    'type' => 'area',
    'is_require' => 1,
    'values' => [
            'title' => 'Text',
            'price' => '1.00',
            'price_type' => 'fixed',
            'max_characters' => '50'

But this gives me the following error:

[MagentoFrameworkValidatorException] Invalid option value

However, I cannot figure out what’s invalid.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

You don’t need to specify values for the option type you are trying to add. Please try example below.

/** @var MagentoCatalogApiDataProductCustomOptionInterface $customOption */
$customOption = $this->objectManager->create('MagentoCatalogApiDataProductCustomOptionInterface');
$customOptions[] = $customOption;

Also, you can find a lot of examples on how to add products, attributes, options, etc in fixtures for integration tests. For instance, take a look in dev/tests/integration/testsuite/Magento/Catalog/_files

Method 2

Here is the another sample code that can import product custom options from array. The basic and required field are added in the code. You can add more field as you need. you can import all of type of custom options with this code. I have checked the code can update options attribute and prices also.

This is a sample array data

$datas = array(
            "sku" => "951391-1-1",
            "attributes" => '[{"title":"Add "I'm a pro" on the back title", "type":"checkbox", "is_require":"0", "sort_order":"1", "values":[{"title":"Add "I'm a pro" on the back", "price":"2.000000", "price_type":"fixed", "sku":null, "sort_order":"1"}, {"title":"Add my name", "price":"6.000000", "price_type":"fixed", "sku":null, "sort_order":"2"}]}, {"title":"Add my name title", "type":"field", "is_require":"0", "sort_order":"2", "price":"0.000000", "price_type":"fixed"}, {"title":"Test area title", "type":"area", "is_require":"0", "sort_order":"3", "price":"16.000000", "price_type":"fixed"}, {"title":"Test file title", "type":"file", "is_require":"0", "sort_order":"5", "price":"4.000000", "price_type":"fixed"}, {"title":"Test dropdown title", "type":"drop_down", "is_require":"0", "sort_order":"6", "values":[{"title":"test dropdown 1", "price":"7.000000", "price_type":"fixed", "sku":null, "sort_order":"1"}, {"title":"test dropdown 2", "price":"8.000000", "price_type":"fixed", "sku":null, "sort_order":"2"}]}, {"title":"Test radio title", "type":"radio", "is_require":"0", "sort_order":"7", "values":[{"title":"Test radio1", "price":"9.000000", "price_type":"fixed", "sku":null, "sort_order":"1"}, {"title":"Test radio2", "price":"10.000000", "price_type":"fixed", "sku":null, "sort_order":"2"}]}, {"title":"Test multiselect title", "type":"multiple", "is_require":"0", "sort_order":"8", "values":[{"title":"Test m-select1", "price":"11.000000", "price_type":"fixed", "sku":null, "sort_order":"1"}, {"title":"Test m-select2", "price":"12.000000", "price_type":"fixed", "sku":null, "sort_order":"2"}]}, {"title":"test date title", "type":"date", "is_require":"0", "sort_order":"9", "price":"13.000000", "price_type":"fixed"}, {"title":"Test data-time title", "type":"date_time", "is_require":"0", "sort_order":"10", "price":"14.000000", "price_type":"fixed"}, {"title":"Test time title", "type":"time", "is_require":"0", "sort_order":"11", "price":"15.000000", "price_type":"fixed"}]'

This is the code

 $options = array();
    foreach ($datas as $data) {
        $_product = $this->_objectManager->create('MagentoCatalogApiProductRepositoryInterface')->get($data['sku'], true);
        $options = json_decode($data['attributes'], true);
        foreach ($options as $arrayOption) {
            $isRequire = $arrayOption['is_require'] == 0 ? true : false;
            $customOption = $this->_objectManager->create('MagentoCatalogApiDataProductCustomOptionInterface');
            if (!in_array($arrayOption['type'], array('drop_down', 'checkbox', 'radio', 'multiple'))) {
            } else {
            $customOptions[] = $customOption;

I think it will help you. Thanks to Igor Melnykov

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment