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

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.

主站蜘蛛池模板: 临沧市| 永顺县| 玛曲县| 高唐县| 云梦县| 通榆县| 彭州市| 广州市| 泰和县| 桦甸市| 宽甸| 夏河县| 文登市| 潜山县| 科技| 开平市| 鞍山市| 临夏市| 平利县| 泗阳县| 湄潭县| 柳江县| 互助| 平舆县| 神农架林区| 灌云县| 永修县| 来宾市| 察雅县| 崇信县| 山丹县| 本溪市| 乌拉特后旗| 富阳市| 平山县| 探索| 凤台县| 榆树市| 白银市| 江口县| 吴江市|