Question

I'm working on creating a custom option for my products automatically any time a product is created. What I've got so far is an observer that fires on the catalog_product_save_before event and runs the following code:

    //check that we haven't made the option already
    $options = $product->getProductOptions();
    foreach ($options as $option) {
        if ($option['title'] == 'Auto Date & Time' && $option['type'] == 'date_time' && !$option['is_delete']) {
            //we've already added the option
            return;
        }
    }
    $options[] = array(
        'title' => $product->getDateLabel(),
        'type' => 'date_time',
        'is_require' => 1,
        'sort_order' => 0,
        'is_delete' => '',
        'previous_type' => '',
        'previous_group' => '',
        'price' => '0.00',
        'price_type' => 'fixed',
        'sku' => ''
    );
    $product->setProductOptions($options);
    $product->setCanSaveCustomOptions(true);
    //this line doesnt make sense here, but it works ... kinda
    $product->save();

If I leave the $product->save() in, I wind up with 2 custom options being created, even though I've check to verify the 2nd time the event fires the return statement is called in the foreach loop.

If I take it out. No custom options are created.

Can someone tell me what I'm doing wrong?
I'm working with Magento 1.7

Was it helpful?

Solution

Until I find the exact problem here is the solution. Instead catalog_product_save_before use the event catalog_product_prepare_save. The downside of this is that the prepare_save event is dispatched only when saving a product from the admin interface or the API. So if you are saving from a custom code this won't get triggered unless you trigger it manually.

I have a hunch that the problem has something to do with the Mage_Catalog_Model_Product::_beforeSave() method. In there there is some processing of the custom options.
But catalog_product_save_before is dispatched after this processing occurs, so while the custom options are processed in Mage_Catalog_Model_Product::_beforeSave() they are actually empty because the event didn't fire yet so they are not added.
If you move the line parent::_beforeSave(); in the method I mentioned at the top of the method, the options are added (still twice, but they are added). I will post more when/if I find the problem.

[EDIT]
Found it. I was somehow right in the lines above.
Like I said the problem is that catalog_product_save_before is dispatched after the custom options are processed. but this is why it doesn't work.
The custom options are saved in Mage_Catalog_Model_Product::_afterSave() by this code:

$this->getOptionInstance()->setProduct($this)
            ->saveOptions();

But $this->getOptionInstance() is populated with options in _beforeSave when the options array is empty in your case. Hence...nothing to save.
If you still want to use the catalog_product_save_before here is the code that should work.

//check that we haven't made the option already
$options = $product->getOptions();
if ($options){
    foreach ($options as $option) {
        if ($option['title'] == 'Auto Date & Time' && $option['type'] == 'date_time' && !$option['is_delete']) {
            //we've already added the option
            return;
        }
    }
}
$option = array(
    'title' => 'Auto Date & Time',
    'type' => 'date_time',
    'is_require' => 1,
    'sort_order' => 0,
    'is_delete' => '',
    'previous_type' => '',
    'previous_group' => '',
    'price' => '0.00',
    'price_type' => 'fixed',
    'sku' => ''
);
//don't use it like this because it has no effect
//$product->setProductOptions($options);
$product->setCanSaveCustomOptions(true);
//use it this way. Populate `$product->getOptionInstance()` directly
$product->getOptionInstance()->addOption($option);
//don't forget to state that the product has custom options
$product->setHasOptions(true);

OTHER TIPS

I just had the same problem, the answer from marius worked great. It took me some time to figure out how to update a custom option though. With the knowledge that $product->getOptionInstance()->addOption() works for saving an option, and setting "is_delete" to 1 removes a option on saving, I came up with this code:

$oldOptions = $product->getOptionInstance()->getOptions();
foreach ($oldOptions as $key => $option){
    if($option['title'] == "Custom Option Title") {
        $oldOptions[$key]['is_delete'] = 1;                 
        $product->getOptionInstance()->addOption($oldOptions[$key]);
    }
}

After deleting you can add your updated custom option with this code:

$newOption = array(
    'title' => "Custom Option Title",
    'type' => 'radio',
    'is_require' => 1,
    'sort_order' => 20,
    'values' => array(
        array(
            'title' => "Value 1 Title",
            'price' => 42.00,
            'price_type' => 'fixed',
            'sku' => "",
            'sort_order' => '1'
        ),
        array(
            'title' => "Value 2 Title",
            'price' => 50,
            'price_type' => 'percent',
            'sku' => "",
            'sort_order' => '2'
        )
    )
);
$product->getOptionInstance()->addOption($newOption);

To create custom option in magento while saving product these is very easy steps.

   $product = Mage::getModel("catalog/product")->load($productid);

    $options[] = array(
            'title' => 'Pet',
            'type' => 'field',
            'is_require' => 0,
            'sort_order' => 0,
        );
    $options[] = array(
            'title' => 'Date',
            'type' => 'field',
            'is_require' => 1,
            'sort_order' => 2,
        );

    $product->setProductOptions(($options));
    $product->setCanSaveCustomOptions(true);
    $product->save();`

If there is already custom option created then you can delete it by following code

$product = Mage::getModel("catalog/product")->load($productid);

    $customOptions = $product->getOptions();

    foreach ($customOptions as $option) {
        $option->delete();
    }

    $product->setHasOptions(0);
    $product->save();

Thanks

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