- Magento PHP Developer's Guide(Second Edition)
- Allan MacGregor
- 667字
- 2021-07-16 13:16:03
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:
- It gets the Magento configuration object.
- Then, it walks through the observer's node children, checking if the defined observer is listening to the current event.
- For each of the available observers, the dispatch event tries to instantiate the observer object.
- 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.
- 大話PLC(輕松動漫版)
- 復(fù)雜軟件設(shè)計之道:領(lǐng)域驅(qū)動設(shè)計全面解析與實戰(zhàn)
- Visual FoxPro程序設(shè)計教程(第3版)
- 前端跨界開發(fā)指南:JavaScript工具庫原理解析與實戰(zhàn)
- Building a Game with Unity and Blender
- Unity 5.x By Example
- Android底層接口與驅(qū)動開發(fā)技術(shù)詳解
- Kubernetes進階實戰(zhàn)
- Advanced UFT 12 for Test Engineers Cookbook
- 愛上C語言:C KISS
- Python Programming for Arduino
- Instant Automapper
- 視窗軟件設(shè)計和開發(fā)自動化:可視化D++語言
- HTML5程序設(shè)計基礎(chǔ)教程
- 微信公眾平臺開發(fā)最佳實踐