2

I have tried several different ways that to add custom options programmatically to a new product in Magento 2. I am doing this from a CLI command and everything is working well except for the custom options which give me an error:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (magento_ee.catalog_product_option, CONSTRAINT CATALOG_PRODUCT_OPTION_PRODUCT_ID_CATALOG_PRODUCT_ENTITY_ROW_ID FOREIGN KEY (product_id) REFERENCES catalog_product_entity (row_id) ON), query was: INSERT INTO catalog_product_option (type, is_require, sort_order) VALUES (?, ?, ?)

Here is the stripped down code:

function __construct(
    \Magento\Catalog\Model\Product $product,
    \Magento\Catalog\Model\Product\Option $option,
    \Magento\User\Model\UserFactory $userFactory,
    \Magento\Framework\App\State $state
)
{
    $this->product = $product;
    $this->option = $option;
    parent::__construct();


    /**
     *
     * Bug fix for known Magento issue where product status cannot be changed in custom CLI command without an admin session
     * https://github.com/magento/magento2/issues/5664
     *
     */
    $model = $userFactory->create()->loadByUsername('admin_username_here');

    $state->emulateAreaCode('adminhtml', function ($model) {
        $session = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Backend\Model\Auth\Session');
        $session->start();
        $session->setUser($model);
        $session->processLogin();
    }, array($model));


}

// Process some stuff here and call setOptions when necessary

// code goes here


private function setOptions(array $dealArray, $lang) {
    if(count((array) $dealArray['offerItems']) > 1) {
        $this->output->writeln('Multiple Options found, processing...');

        $values = [];
        $i = 1;
        foreach($dealArray['offerItems'] as $item) {
            $this->output->writeln('Setting option: '.$item->$lang->offerItemSKU);

            $values[] = array(
                'title'             => $item->$lang->offerItemValue,
                'price'             => $this->product->getPrice(),
                'price_type'        => "fixed",
                'sku'               => $item->$lang->offerItemSKU,
                'sort_order'        => $i
            );

            $i++;
        }

        $optionArray = array(
                "sort_order"    => 1,
                "title"         => "Options",
                "type"          => "drop_down",
                "is_require"    => 1,
                "values"        => $values
            );

        $this->output->writeln('Setting options for SKU: '.$this->product->getSku().PHP_EOL.print_r($optionArray, true));
        $this->option->addData($optionArray);
        $this->option->save();

        $this->product->setOptions([$this->option]);
        $this->option->clearInstance();

    } else {
        $this->output->writeln('No Options found.');
    }
}
  • You wants to add additional custom options for the product right? – shivashankar m Jul 25 '17 at 7:12
  • You can also add Custom Options in this file( vendor/magento/module-catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php) – shivashankar m Jul 25 '17 at 7:17
2

I found the solution:

Instead of calling setProductId like this:

$this->option->setProductId($this->product->getId());

I had to call it like this:

$this->option->setProductId($this->product->getData('row_id'));

It seems to want the row_id instead of the entity_id, which is inconsistent with the rest of Magento2 implementations.

Final code looks like this:

private function setOptions(array $dealArray, $lang) {
    if(count((array) $dealArray['offerItems']) > 1) {
        $this->product->setHasOptions(1);
        $this->product->setCanSaveCustomOptions(true);
        $this->output->writeln('Multiple Options found, processing...');

        $values = [];
        $i = 1;
        foreach($dealArray['offerItems'] as $item) {

            $values[] = array(
                'title'             => $item->$lang->offerItemValue,
                'price'             => $this->product->getPrice(),
                'price_type'        => "fixed",
                'sku'               => $item->$lang->offerItemSKU,
                'sort_order'        => $i
            );

            $i++;
        }

        $this->option->setTitle('Options');
        $this->option->setType('drop_down');
        $this->option->setSku($this->product->getId().'_option');
        $this->option->setProductId($this->product->getData('row_id'));
        $this->option->setProductSku($this->product->getSku());
        $this->option->setIsRequire(true);
        $this->option->setSortOrder(1);
        $this->option->setValues($values);
        $this->option->save();

        $this->product->setOptions([$this->option]);

    } else {
        $this->output->writeln('No Options found.');
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.