想必一些初学者在magento中会看到很多Mage::dispatchEvent()这样的方法吧,可能也会和我第一次见时候一样会想这是什么呢?但是如果说magento中的重写方法想必应该会知道吧,但是重写存在一些缺点,当有多个模块的时候,重写同一个类(class)时,那它们互相将会有冲突,只有一个模块将会正常工作,而这时候就是Mage::dispatchEvent()方法发挥作用的时候了。
Mage::dispatchEvent()方法叫作事件的分发,而事件的分发的使用频率应该高于对类的重写(overriding),为什么这么说呢,因为事件的分发可以弥补重写的缺点,使用事件的话,可以多个模块很轻松的去调用它。
Magento中的事件也是根据观察者(Observer)设计模式,它是这样工作的,在Magento核心代码中,许多地方都分发了事件, 每一个事件都有自己唯一的名字和其他相关的参数,在我们自己的模块中,同样也可以调用这些事件,当 Magento 分发这些事件的时候,在我们自己模块中的一个方法将会被触发,在这个方法中我们可以进行相关的操作。Magento调用 Mage::dispatchEvent() 方法来分发事件,你全盘搜索一下的话,会发现Magento代码中很多地方都调用了
举个例子:
Mage::dispatchEvent('dispatch_event_test',
array(
'key_one' => 'test 1',
'key_two' => 'test 2'
)
);
每一个事件都有自己的名字和相关参数在上述方法中,‘dispatch_event_test’ 就是该分发事件的名字,
array(
‘key_one’ => ‘test 1’,
‘key_two’ => ‘test 2’
)
就是相关参数 在我们的模块中如果想调用(subscribe)或监听(listen)这个事件的时候,需要添加如下代码至config.xml文件中
<events>
<dispatch_event_test><!-- 事件的名字 -->
<observers>
<dispatch_event_test_observer><!-- 任何唯一的标示符 -->
<class>event/observer</class><!-- 事件执行的类的路径(class) -->
<method>eventTest</method><!-- 方法名 -->
</dispatch_event_test_observer>
</observers>
</dispatch_event_test>
</events>
现在可以在任意模块的Model文件夹中建立一个Observer.php文件,随后定义一个方法名为:eventTest()
class Event_Model_Observer
{
public function eventTest(Varien_Event_Observer $observer)
{
$key_one = $observer->getEvent()->getKeyOne();
$key_two = $observer->getEvent()->getKeyTwo();
echo $key_one;
echo PHP_EOL;
echo $key_two;
echo PHP_EOL;
}
}
得到的结果如下:
test 1
test 2
除此之外,每当一个模块(Model)执行完保存之后,会触发总父类下的save方法,而save方法中存在_beforeSave和_afterSave两个方法,而方法中分别又会触发两个事件
Mage::dispatchEvent('model_save_before', array('object'=>$this));
Mage::dispatchEvent($this->_eventPrefix.'_save_before', $this->_getEventData());
Mage::dispatchEvent('model_save_after', array('object'=>$this));
Mage::dispatchEvent($this->_eventPrefix.'_save_after', $this->_getEventData());
如果想在保存前或保存后添加相应的信息数据可以重写_beforeSave和_afterSave,样例:
protected function _beforeSave()
{
parent::_beforeSave();
if (!$this->getParentId() && $this->getShipment()) {
$this->setParentId($this->getShipment()->getId());
}
return $this;
}
这里使用parent::_beforeSave();的意思是将父类所有的代码功能拿过来直接使用,然后在后面添加自己想加入的相关数据即可。