Question

I'm trying to add custom option programmatically after product save event. I've found some solution on stackexchange which are not working for me. So I'm posting all my codes here for finding any errors in it.

This is my observer class:

class ProductSaveAfter implements \Magento\Framework\Event\ObserverInterface
{

    /**
     * Execute observer
     *
     * @param \Magento\Framework\Event\Observer $observer
     * @return void
     */
     protected $ObjectManager;
     protected $product;

   public function __construct(
     \Magento\Framework\ObjectManagerInterface $ObjectManager,
     \Magento\Catalog\Model\Product $product
  ){

    $this->_objectManager = $ObjectManager;
    $this->_product = $product;

  }
    public function execute(
        \Magento\Framework\Event\Observer $observer
    ) {

         $_product = $observer->getProduct();  // you will get product object
         $productId = $_product->getId();
        try{            
                $customOption = $this->_objectManager->create('Magento\Catalog\Api\Data\ProductCustomOptionInterface');

                $var = NULL;
                $customOption
                ->setOptionId($var)
                ->setProductId($productId)
                ->setType('field')
                ->setIsRequire("0")
                ->setSku("")
                ->setMaxCharacters("0") 
                ->setFileExtension("")
                ->setImageSizeX("0")
                ->setImageSizeY("0")
                ->setSortOrder("1")
                ->setDefaultTitle("Profile Name")
                ->setStoreTitle("Profile Name")
                ->setTitle("Profile Name")                
                ->setDefaultPrice("0.00")
                ->setDefaultPriceType("fixed") 
                ->setStorePrice("0.00")
                ->setStorePriceType("0.00")
                ->setPrice("0.00")
                ->setPriceType('fixed')                               
                ->setRecordId("0")                
                ->setProductSku($_product->getSku());               
                $customOptions[] = $customOption;                
                $_product->setOptions($customOptions)->save();

            } catch (\Exception $e) {
                var_dump($e->getMessage());

            }
    }
}

After saving data from backend the page does not respond due to this code. What is the problem with it?

Another instance of code is as follows which I found in this link https://magento.stackexchange.com/questions/97014/magento2-programmatically-adding-a-custom-option

<?php
namespace Custom\Addcustomoption\Observer\Catalog;
class ProductSaveAfter implements \Magento\Framework\Event\ObserverInterface
{

    /**
     * Execute observer
     *
     * @param \Magento\Framework\Event\Observer $observer
     * @return void
     */
     protected $ObjectManager;
     protected $product;

   public function __construct(
     \Magento\Framework\ObjectManagerInterface $ObjectManager,
     \Magento\Catalog\Model\Product $product
  ){

    $this->_objectManager = $ObjectManager;
    $this->_product = $product;

  }
    public function execute(
        \Magento\Framework\Event\Observer $observer
    ) {

         $_product = $observer->getProduct();  // you will get product object
         $productId = $_product->getId();
        try{            
                /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterface $customOption */
                $customOption = $this->objectManager->create('Magento\Catalog\Api\Data\ProductCustomOptionInterface');
                $customOption->setTitle('Text')
                    ->setType('area')
                    ->setIsRequire(true)
                    ->setSortOrder(1)
                    ->setPrice(1.00)
                    ->setPriceType('fixed')
                    ->setMaxCharacters(50)
                    ->setProductSku($_product->getSku());
                $customOptions[] = $customOption;
                $_product->setOptions($customOptions)->save();

            } catch (\Exception $e) {
                var_dump($e->getMessage());
            }
    }
}

The problem with this is that the product gets saved but no custom options are seen in backend. Any suggestions, solutions to this problem?

Was it helpful?

Solution

To make it works, please try to use the following example.

Your new M2 module directory structure:

app/code/Stackoverflow/Catalog
├── etc
│   ├── adminhtml
│   │   └── events.xml
│   └── module.xml
├── Observer
│   └── AddCustomOptions.php
├── composer.json
└── registration.php

I assume that you already knew how to create a basic module in Magento 2, I will move inside the major files in this situation in details

app/code/Stackoverflow/Catalog/etc/adminhtml/events.xml

<?xml version="1.0"?>
<!--
  ~ Copyright © 2017 Toan Nguyen. All rights reserved.
  ~ See COPYING.txt for license details.
  -->

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="controller_action_catalog_product_save_entity_after">
        <observer name="product_add_custom_options" instance="Stackoverflow\Catalog\Observer\AddCustomOptions"/>
    </event>
</config>

app/code/Stackoverflow/Catalog/Observer/AddCustomOptions.php

<?php
/**
 * Copyright © 2017 Toan Nguyen. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Stackoverflow\Catalog\Observer;

use Magento\Catalog\Model\Product\Option;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Catalog\Model\ProductRepository;
use Magento\Catalog\Api\Data\ProductCustomOptionInterface;
use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory as CustomOptionFactory;

class AddCustomOptions implements ObserverInterface
{
    /**
     * @var ProductRepository
     */
    protected $productRepository;

    /**
     * @var CustomOptionFactory
     */
    protected $customOptionFactory;

    /**
     * @var ProductCustomOptionInterface
     */
    protected $productCustomOption;

    /**
     * AddCustomOptions constructor.
     *
     * @param ProductRepository            $productRepository
     * @param ProductCustomOptionInterface $productCustomOption
     */
    public function __construct(
        ProductRepository $productRepository,
        ProductCustomOptionInterface $productCustomOption
    ) {
        $this->productRepository = $productRepository;
        $this->productCustomOption = $productCustomOption;
    }

    /**
     * {@inheritdoc}
     */
    public function execute(Observer $observer)
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $observer->getData('product');
        $customOptionData = [
            Option::KEY_TITLE => 'Text',
            Option::KEY_TYPE => 'area',
            Option::KEY_IS_REQUIRE => true,
            Option::KEY_SORT_ORDER => 1,
            Option::KEY_PRICE => 1.00,
            Option::KEY_PRICE_TYPE => 'fixed',
            Option::KEY_MAX_CHARACTERS => 50,
            Option::KEY_PRODUCT_SKU => $product->getSku()
        ];
        $customOption = $this->getCustomOptionFactory()->create(['data' => $customOptionData]);
        $customOptions[] = $customOption;
        $product->setOptions($customOptions)->setCanSaveCustomOptions(true)->save();
    }

    /**
     * @return CustomOptionFactory
     */
    private function getCustomOptionFactory()
    {
        if (null === $this->customOptionFactory) {
            $this->customOptionFactory = \Magento\Framework\App\ObjectManager::getInstance()
                ->get('Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory');
        }
        return $this->customOptionFactory;
    }
}

Hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top