官术网_书友最值得收藏!

Events and observers

The event and observer pattern is probably one of Magento's more interesting features, as it allows developers to extend Magento in critical parts of the application flow.

In order to provide more flexibility and facilitate interaction between the different modules, Magento implements an Event/Observer pattern. This pattern allows modules to be loosely coupled.

There are two parts to this system, an Event dispatch with the object and event information and an Observer listening to a particular event:

Event dispatch

Events are created or dispatched using the Mage::dispatchEvent() function. The core team has already created several events on critical parts of the core. For example, the Model abstract class Mage_Core_Model_Abstract calls two protected functions every time a model is saved: _beforeSave() and _afterSave() on each of these methods two event are fired.

protected function _beforeSave()
{
    if (!$this->getId()) {
        $this->isObjectNew(true);
    }
    Mage::dispatchEvent('model_save_before', array('object'=>$this));
    Mage::dispatchEvent($this->_eventPrefix.'_save_before', $this->_getEventData());
    return $this;
}

protected function _afterSave()
{
    $this->cleanModelCache();
    Mage::dispatchEvent('model_save_after', array('object'=>$this));
    Mage::dispatchEvent($this->_eventPrefix.'_save_after', $this->_getEventData());
    return $this;
}

Each function fires a generic model_save_after event, and then a dynamic version based on the type of object being saved. This gives us a wide range of possibilities to manipulate objects through observers.

The Mage::dispatchEvent() method takes two parameters, the first is the event name and the second is an array of data that is received by the observer. We can pass values or objects in this array. This comes in handy if we want to manipulate the objects.

In order to understand the details of the event system, let's take a look at the dispatchEvent() method:

public static function dispatchEvent($name, array $data = array())
{
    $result = self::app()->dispatchEvent($name, $data);
    return $result;
}

This function is actually an alias to the dispatchEvent() function inside the App core class, located in Mage_Core_Model_App:

public function dispatchEvent($eventName, $args)
{
    foreach ($this->_events as $area=>$events) {
        if (!isset($events[$eventName])) {
            $eventConfig = $this->getConfig()->getEventConfig($area, $eventName);
            if (!$eventConfig) {
                $this->_events[$area][$eventName] = false;
                continue;
            }
            $observers = array();
            foreach ($eventConfig->observers->children() as $obsName=>$obsConfig) {
                $observers[$obsName] = array(
                    'type'  => (string)$obsConfig->type,
                    'model' => $obsConfig->class ? (string)$obsConfig->class : $obsConfig->getClassName(),
                    'method'=> (string)$obsConfig->method,
                    'args'  => (array)$obsConfig->args,
                );
            }
            $events[$eventName]['observers'] = $observers;
            $this->_events[$area][$eventName]['observers'] = $observers;
        }
        if (false===$events[$eventName]) {
            continue;
        } else {
            $event = new Varien_Event($args);
            $event->setName($eventName);
            $observer = new Varien_Event_Observer();
        }

        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);
        }
    }
    return $this;
}

The dispatchEvent() method actually does all the work on the Event/Observer model:

  1. It gets the Magento configuration object.
  2. Then, it walks through the observer's node children, checking if the defined observer is listening to the current event.
  3. For each of the available observers, the dispatch event tries to instantiate the observer object.
  4. Lastly, Magento tries to call the corresponding observer function mapped to this particular event.

Observer bindings

Now, dispatching an event is only part of the equation. We also need to tell Magento which observer is listening to each event. Not to our surprise, observers are specified through the config.xml file. As we saw before, the dispatchEvent() function queries the configuration object for available observers. Let's take a look at an example config.xml file:

<events>
    <event_name>
        <observers>
            <observer_identifier>
                <class>module_name/observer</class>
                <method>function_name</method>
            </observer_identifier>
        </observers>
    </event_name>
</events>

The event node can be specified in each of the configuration sections (admin, global, frontend, and so on) and we can specify multiple event_name children nodes. The event_name node has to match the event name used in the dispatchEvent() function.

Inside each event_name node, we have a single observer node that can contain multiple observers, each with a unique identifier.

Observer nodes have two properties, <class>, which points to our observer model class, and <method>, which points to the actual method inside the observer class. Let's analyze an example observer class definition:

class Namespace_Modulename_Model_Observer
{
    public function methodName(Varien_Event_Observer $observer)
    {
        //some code
    }
}
Note

One interesting thing about observer models is that they don't extend to any other Magento class.

主站蜘蛛池模板: 全南县| 晋宁县| 福州市| 新巴尔虎左旗| 万全县| 辰溪县| 西和县| 紫云| 启东市| 诸城市| 桂平市| 日土县| 杭锦后旗| 金溪县| 社旗县| 威海市| 信阳市| 松滋市| 石家庄市| 霍州市| 永昌县| 镇远县| 沈丘县| 乳源| 九龙坡区| 闽侯县| 兰州市| 宣城市| 增城市| 苏尼特左旗| 敖汉旗| 晋江市| 织金县| 浙江省| 聂拉木县| 锡林郭勒盟| 北碚区| 大姚县| 饶河县| 望城县| 竹溪县|