Tuesday, April 23, 2013

Magento observer method arguments - what are they?

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:

Unknown said...

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 

Labels