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.
1 comment:
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
magento development company in bangalore
Post a Comment