I'm using observer method sales_order_save_before to do some operations based on order state

   $order = $observer->getEvent()->getOrder();
   $initialState = $order->getOrigData('state');
   $newState = $order->getData('state');
   if($initialState != $newState && $newState == 'processing'){
    // Do some operation          
   if($initialState != $newState && $newState == 'complete'){
    // Do some operation          

First validation is working fine whereas in second if loop both the conditions are not being true at the same time.

I did some modifications in order and digged dipper into its status. What I see is when first time order is placed it's status and state is processing . When order is shipped and invoiced in admin it's status becomes complete but state still remains processing. When the status is complete and I write a comment on this order then it's state becomes complete due to which second if loop is not working.

How I can validate the loop when the order state becomes complete ? (initialState should be different than newState).

1 Answer 1


The problem is that the state is changed after the sales_order_save_before event has been dispatched.

Take a look at Mage_Sales_Model_Order:

 * Processing object before save data
 * @return Mage_Core_Model_Abstract
protected function _beforeSave()
    parent::_beforeSave();           <-- here the event is dispatched
    $this->_checkState();            <-- here the new state is set based on current
    ...                                  state and other conditions

Since there is no other event fired before the actual saving, your best bet is to observe sales_order_save_after and save the order a second time if you must.

  • But if I observe sales_order_save_after, $order->getOrigData('state'); will not give proper result so I won't be able to do a proper comparison, right?
    – amitshree
    Jul 22, 2015 at 19:01
  • 1
    I don't think so. orig_data should only be reset after load. But if I'm wrong, you still can back it up in a sales_order_save_before observer: $this->_origData = $order->getOrigData(); and read it in the sales_order_save_after observer (assuming both are in the same class and registered as singleton) Jul 22, 2015 at 19:07
  • That works :) Though I would like to know how I can back it up in sales_order_save_before and use in sales_order_save_after . Should I dispatch sales_order_save_after method inside sales_order_save_before with backed parameter? Somewhere I read, I can also use registry in this case.
    – amitshree
    Jul 22, 2015 at 20:10
  • 1
    No need for the registry. As hinted above, by default observers are singletons and you will implement both observer methods in the same class. So you can simply add a property to the observer. Jul 22, 2015 at 20:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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