One of the difficulties I have developing event observers for Magento is that I don't know what the arguments to the observer methods are. Most examples show a single argument, typically named $observer. What is it and what are its methods and attributes? I have had difficulty finding this out.
Initially I dumped the argument to a log using print_r:
public function observer_method($observer) {
Mage::log(
"Observer observer_method executing with: " .
print_r($observer,true),
null,
'MyModule.log'
);
}
This worked fine for a while, then I tried this with the argument passed for the sales_order_item_after_save event and quickly ran out of memory. The problem is that the passed object has cyclical links and print_r doesn't notice the recursion: it just keeps printing until it runs out of memory. The var_dump function has the same problem.
Fortunately, most objects in Magento are derived from the Varien_Object class and this class has a debug() method which handles recursion. So, a more general solution to inspecting data in Magento is to combine print_r with debug:
public function observer_method($observer) {
Mage::log(
"Observer observer_method executing with: " .
print_r($observer->debug(),true),
null,
'MyModule.log'
);
}
The debug method returns an array with no recursion and print_r renders that to a string.
Another approach is to find where Mage::dispatchEvent is executed for the event of interest and examine the arguments that are passed. This is easy for some events: Mage::dispatchEvent is called with the event name as a literal argument. One can grep the source for these. But, again, the case of sales_order_item_after_save was more challenging. Grepping the source for this event yielded nothing except observers. Eventually I grepped for 'sales_order_item' and 'after_save' separately and found where the event might be dispatched...
In app/code/core/Mage/Core/Model/Abstract.php one finds:
/**
* Processing object after save data
*
* @return Mage_Core_Model_Abstract
*/
protected function _afterSave()
{
$this->cleanModelCache();
Mage::dispatchEvent('model_save_after', array('object'=>$this));
Mage::dispatchEvent($this->_eventPrefix.'_save_after', $this->_getEventData());
return $this;
}
So, since I can't find it elsewhere, I'm guessing whatever issues the sales_order_item_save_after event is calling _afterSave() with _eventPrefix set to 'sales_order_item'.
I found one class (Mage_Sales_Model_Order_Item in app/code/core/Mage/Sales/Model/Order/Item.php) that extends Mage_Core_Model_Abstract and sets a property _eventPrefix to 'sales_order_item'. It doesn't call _afterSave itself, so I still don't know exactly what the passed arguments are, but getting closer. The Mage_Sales_Model_Order_Item class doesn't have a _getEventData() method, so it is most likely that _getEventData from class Mage_Core_Model_Abstract is the culprit.
From Mage_Core_Model_Abstract:
/**
* Get array of objects transfered to default events processing
*
* @return array
*/
protected function _getEventData()
{
return array(
'data_object' => $this,
$this->_eventObject => $this,
);
}
and
/**
* Parameter name in event
*
* In observe method you can use $observer->getEvent()->getObject() in this case
*
* @var string
*/
protected $_eventObject = 'object';
But, class Mage_Sales_Model_Order_Item has:
protected $_eventObject = 'item';
So, the argument to the event observer for sales_order_item_save_after should be an array with two elements: 'data_object' and 'item', but both referring to the same data: the Mage_Sales_Model_Order_Item instance.
Maybe next time I'll try generating a stack trace in the observer method. That should help to pin down the method that dispatches the event quickly.
Great blog. All posts have something to learn. Your work is very good and i appreciate you and hoping for some more informative posts.keep writing
ReplyDeletemagento development company in bangalore