Saturday, April 27, 2013

Magento observer types

When configuring an Observer in Magento, one of the configuration parameters is 'type'.

For example, the Magento wiki has an example of customizing Magento using an event observer, where the module configuration is:

<?xml version="1.0"?>
    <config>
      <global>
        <models>
            <xyzcatalog>
                 <class>Xyz_Catalog_Model</class>
            </xyzcatalog>
        </models>
        <events>
          <catalog_product_get_final_price>
            <observers>
              <xyz_catalog_price_observer>
                <type>singleton</type>
                <class>Xyz_Catalog_Model_Price_Observer</class>
                <method>apply_discount_percent</method>
              </xyz_catalog_price_observer>
            </observers>
          </catalog_product_get_final_price>     
        </events>
      </global>
    </config>


Note the 'type' key in the configuration. In this case, the content is 'singleton', but there is no explanation of what this aspect of the configuration is about.

The type is dealt with in the dispatchEvent method of class Mage_Core_Model_App, method dispatchEvent, which is executed from class Mage, method dispatchEvent (the latter seems to be what is executed generally throughout the code but it is just a thin wrapper around the former). This function ends with a loop that executes each observer registered for the event in turn, as follows:

            foreach ($events[$eventName]['observers'] as $obsName=>$obs) {
                $observer->setData(array('event'=>$event));
                Varien_Profiler::start('OBSERVER: '.$obsName);
                switch ($obs['type']) {
                    case 'disabled':
                        break;
                    case 'object':
                    case 'model':
                        $method = $obs['method'];
                        $observer->addData($args);
                        $object = Mage::getModel($obs['model']);
                        $this->_callObserverMethod($object, $method, $observer);
                        break;
                    default:
                        $method = $obs['method'];
                        $observer->addData($args);
                        $object = Mage::getSingleton($obs['model']);
                        $this->_callObserverMethod($object, $method, $observer);
                        break;
                }
                Varien_Profiler::stop('OBSERVER: '.$obsName);
            }
Note that there are really only three cases for type: 'disabled', in which case no observer is called; 'object' or 'model', which are equivalent, in which case Mage::get_Model is called; or any other values (any other value is equivalent - this includes 'singleton'), in which case Mage::getSingleton is called. Mage::get_Model and Mage::getSingleton are both passed the value of the 'model' parameter of the observer configuration.

Mage::getSingleton($class) calls Mage::getModel($class) but it caches the return value and calls Mage:;getModel only once. Subsequent calls for the same $class return the cached instance rather than a new instance. In contract, Mage::getModel($class) returns a new instance of the class every time.

So, for new modules, one might use the types: 'disabled', 'model' or 'singleton'.

Type 'disabled': the observer class is not instantiated and the observer method is not executed.

Type 'model': a new instance of the observer class is instantiated for each event and the observer method of that instance is executed.

Type 'singleton': a single instance of the observer class is instantiated and the observer method of that single instance is executed for each event.

2 comments:

Ricardo Martins said...

Very useful post. Helped me to understand it differences and find out how magento lead with getsingleton and getModel.
Thks.

Unknown said...

Thanks for the best blog.it was very useful for me.keep sharing such ideas in the future as well.this was actually what i was looking for,and i am glad to came here!
magento development company in bangalore 

Labels