3

I would like to change some options of the items present in the cart.

On the checkout_cart_add_product_complete.

I launch the following function:

 public function TreatShipConflicts($observer)
 {
    //Analyse du nouveau produit ajouté au panier

    $_cart = Mage::getModel('checkout/cart')->getQuote();
    $_items = $_cart->getAllItems(); 

    foreach ($_items as $_item) {

        $_options = $_item->getProduct()->getTypeInstance(true)->getOrderOptions($_item->getProduct());
        $Flag = 0;
        $optionid = 0;
        Mage::log("CART to be changed");
        foreach($_options["options"] as $_option) 
        {
            if ($_option['label'] == 'ShipMth')
            {
                $Flag = 1;
                $optionid = $_option['option_id'];
            }       
        }    
        Mage::log($optionid);
        if ($Flag == 1) {

        $optionnb = "option_".$optionid;

        $item22 = Mage::getSingleton('checkout/session')->getQuote()->getItemById($_item->getId());
        $options = $item22->getOptions();       

        foreach ($options as $option) {
            switch (true) {
                case ($option->getCode() == 'info_buyrequest') :
                    $unserialized = unserialize($option->getValue());
                    $unserialized['options'][$optionid] = 'TNT';
                    $option->setValue(serialize($unserialized));
                    break;
                case ($option->getCode() == $optionnb) :
                    $option->setValue('TNT');
                    break;
                }
        }
        $item22->setOptions($options)->save(); 
        Mage::getSingleton('checkout/cart')->save();
    }
 }  

}

All my items option are changed EXCEPT the last one (the last added in cart i.e. the one that triggered the event)…

(I was before triggering on the checkout_cart_product_add_after event, but read on a so post that the item was not yet saved, and then it was impossible to customize its options at this step. I then changed to checkout_cart_add_product_complete, (where at this point it was said to be really an Item and really in cart, but got the same result..)

Thank you for your help,

EDIT: An info that maybe can help. When I add my first item in cart (cart empty) (item that then will be the unsaved one), I have an error on $options = $item22->getOptions();which means that it is clearly not the same item type as the others…

EDIT 2: still searching… and found a new strange thing : when my cart has items in it and that I remove the last added item (the one with unsaved options), when I add a new item in cart, I have got the same error as the first EDIT ! If I remove another item (not the last one), I can add an time without the $options = $item22->getOptions(); error but the option modification is still unsaved…

EDIT3: I checked the database using phpmyadmin and the "sales_flat_quote_item_option" table still have the unmodified options values for the last added item

2
+25

I'm not sure, but I think that you should get last addet item that way:

$item = $observer->getQuoteItem();
  • options are not saved in the quote item. only in orders and quote. furthermore, when I loop all the items, the last one is present... – Alexglvr Apr 26 '15 at 9:36
  • As far as I know, you can get options that way: $buyRequest = $item->getBuyRequest(); – SeStro Apr 26 '15 at 17:52
2

As Sebastian mentioned you'll need to use the $observer parameter of the event to get the cart and its contents at the current state of the event. As using the singleton Mage::getModel('checkout/cart')->getQuote(); will only return the quotes saved contents before the event is observed, causing the last item (the item to trigger the observer) to not have the proper options as it is happening before collectTotals.

$quote = $observer->getEvent()->getQuote();
foreach ($quote->getAllItems() as $item) {
    $product = $item->getProduct();
}

You can also try observing sales_quote_save_before OR calling to re-collect totals.

$quote->setTotalsCollectedFlag(false)->collectTotals();
session_write_close();

Also, avoid calling the session and cart Mage::getModel as the $observer will have the details you need without any unforseen issues of reinitialization.

Related:

  • I get an error on -> getAllItems() (event checkout_cart_product_add_after) – Alexglvr Apr 28 '15 at 14:59
1

I found the solution to modify the last added item (on checkout_cart_product_add_after event) :

It is globally like the code I posted i.e. getting the cart items with

$_cart = Mage::getModel('checkout/cart')->getQuote();
$_items = $_cart->getAllItems(); 

but if the last added item has to be modified, here is the way :

$_quoteitem = $observer->getEvent()->getQuoteItem();
$buyRequest = $_quoteitem->getOptionByCode('info_buyRequest');
$buyRequestArr = unserialize($buyRequest->getValue());
$buyRequestArr['options'][$shipoptid] = 'TNT';
$buyRequest->setValue(serialize($buyRequestArr));

$optionship = $_quoteitem->getOptionByCode($shipoptcode);
$optionship['value']='TNT';

and let magento save it !

for the other items (already in cart) :

$item22 = Mage::getSingleton('checkout/session')->getQuote()->getItemById($_item->getId());
$options = $item22->getOptions();       

foreach ($options as $option) {
    switch (true) {
        case ($option->getCode() == 'info_buyrequest') :
            $unserialized = unserialize($option->getValue());
            $unserialized['options'][$optionid] = 'TNT';
            $option->setValue(serialize($unserialized));
            break;
        case ($option->getCode() == $optionnb) :
            $option->setValue('TNT');
            break;
        }
}
$item22->setOptions($options)->save(); 
Mage::getSingleton('checkout/cart')->save();

if it can help...

0

I remember sitting on an issue like this before, however mine was slightly different:

  1. add product 1 - options didn't update.
  2. add product 2 - options for product 1 updated.
  3. add product 3 - options for product 2 updated.
  4. etc.

It was always the last item that didn't update.

My solution was this at the end before the cart save:

Mage::getSingleton('customer/session')->setCartWasUpdated(true);
$cart->save();

Where $cart is the cart object Mage::getModel("checkout/cart");

Also, to debug in your instance, i always recommend wrapping your logic in try / catch blocks as good practice. Any exceptions thrown can be logged and will be easier to debug.

And also move away from the switch / case statements, you are better off using if elseif and else. Your switch case only has 2 cases and no default, so if there was by any chance a case where the option code didn't match one of your cases, then an option value would never be set, which may also be the problem. To make 100% sure add a default case and log the output.

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.