Magento – Modifying custom options of an item when adding it to the cart

cartcustom-optionsevent-observer

I am listening to the sales_quote_save_before event to notice when an item is added to the cart. Once its fired, I iterate through the items options like this:

$quote = $observer->getEvent()->getQuote();

foreach ($quote->getAllItems() as $item) {
    $options = $item->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct());

    foreach($options['options'] as $option) {

         if($option['label'] == 'myOptionA') {
              // Here I want to change the selected value for the option  
         }
     }
}

As you see, as soon as a certain option (myOptionA in the example) is reached, I want to change the selected option. So lets say myOptionA is a drop down and has 4 possible values. In case value 1 is selected, I want to set value 4 for that item. So when the cart is finished loading it should have value 4 for myOptionA. Not just its name, but its price as well. How could I do that?

Best Answer

You could write an observer for the event catalog_product_type_prepare_full_options instead, which is the last event in the add to cart process before the product is actually added to the cart and after the custom options are prepared.

In the observer you have the following parameters available:

  • transport: Transport object for all custom options, so you can change tehem in the observer. transport->options is an array in the form option_id => option_value. Attention, transport itself is a stdClass object, not an instance of Varien_Object, as you might expect. So there are no getter and setter methods for transport->options.
  • product: The product that will be converted to a quote item later on.
  • buy_request: The buyRequest object, you can read it here and still modify it as well. It's a Varien_Object that contains amongst others:

    • product: The product id
    • options: Array of custom options in the form:

      option_id => value
      

Source and more info: info_buyRequest reference

So your observer might look like this:

$transport = $observer->getTransport();
if (isset($transport->options[OPTION_A_ID]) && $transport->options[OPTION_A_ID] == 1) {
    $transport->options[OPTION_A_ID] = 4;
}

$buyRequest= $observer->getBuyRequest();
$buyRequestOptions = $buyRequest->getOptions();
if (isset($buyRequestOptions[OPTION_A_ID]) && $buyRequestOptions[OPTION_A_ID] == 1) {
    $buyRequestOptions[OPTION_A_ID] = 4;
}
$buyRequest->setOptions($buyRequestOptions);

The first part (changing $transport) is relevant to actually change the value of option OPTION_A_ID. The second part (changing $buyRequest) is optional, it will just delete all traces of the value that the customer selected and if he reorders the order, the new value will be immediately selected because the buy request gets "executed" with the changed parameters. You have to decide, if that's what you want.