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
, CONSTRAINTCATALOG_PRODUCT_OPTION_PRODUCT_ID_CATALOG_PRODUCT_ENTITY_ROW_ID
FOREIGN KEY (product_id
) REFERENCEScatalog_product_entity
(row_id
) ON), query was: INSERT INTOcatalog_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.');
}
}
Best Answer
I found the solution:
Instead of calling setProductId like this:
I had to call it like this:
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: