- 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.
- The Supervised Learning Workshop
- Hands-On Full Stack Development with Go
- C和C++游戲趣味編程
- Android玩家必備
- 細說Python編程:從入門到科學計算
- Apache Camel Developer's Cookbook
- Everyday Data Structures
- 例解Python:Python編程快速入門踐行指南
- PostgreSQL 12 High Availability Cookbook
- Internet of Things with Arduino Cookbook
- Learning Redis
- Java Web開發任務教程
- HTML 5與CSS 3權威指南(第4版·上冊)
- Mastering Citrix? XenDesktop?
- WordPress 3.7 Complete(Third Edition)