系统学习magento二次开发,推荐小册:《Magento中文全栈二次开发 》
本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。
Magento有一个整洁的发布-订阅模式实现,我们称之为事件和观察者。通过在触发某些操作时调度事件,我们可以运行自定义代码来响应触发的事件。
这些事件是使用Magento\Framework\event\Manager类调度的,该类实现了Magento\ Framework\event \ ManagerInterface。要调度事件,我们只需调用事件管理器实例的调度方法,为其提供我们正在调度的事件的名称以及我们希望传递给观察者的可选数据数组
如下例所示,该示例取自<MAGENTO_DIR>/module-customer/Controller/Account/CreatePost.php文件:
$this - > _eventManager - > dispatch('customer_register_success', ['account_controller' => $this, 'customer' => $customer]);
观察者是通过events.xml文件注册的,如<MAGENTO_DIR>/module persistent/etc/frontend/events.xml中的以下示例所示:
<event name="customer_register_success"> <observer name="persistent" instance="Magento\Persistent\Observer\RemovePersistentCookieOnRegisterObserver" /> </event>
通过在整个<MAGENTO_DIR>目录的*.php文件中查找eventManager->dispatch字符串,我们可以看到数百个事件示例,分布在MAGENTO的大多数模块中。
虽然所有这些事件都具有相同的技术重要性,但我们可以说,其中一些事件可能比其他事件在日常基础上使用得更多。这使得花一些时间研究以下类及其发送的事件变得值得:Magento\Framework\App\Action\Action类,具有以下事件:
controller_action_predispatch' controller_action_predispatch_' . $request->getRouteName()' controller_action_predispatch_' . $request->getFullActionName()' controller_action_postdispatch_' . $request->getFullActionName()' controller_action_postdispatch_' . $request->getRouteName() controller_action_postdispatch
Magento\Framework\Model\AbstractModel类,包含以下事件:
model_load_before$this->_eventPrefix . '_load_before' model_load_after$this->_eventPrefix . '_load_after' model_save_commit_after$this->_eventPrefix . '_save_commit_after' model_save_before$this->_eventPrefix . '_save_before' model_save_afterclean_cache_by_tags$this->_eventPrefix . '_save_after' model_delete_before$this->_eventPrefix . '_delete_before' model_delete_afterclean_cache_by_tags$this->_eventPrefix . '_delete_after' model_delete_commit_after$this->_eventPrefix . '_delete_commit_after'$this->_eventPrefix . '_clear'
Magento\Framework\Model\ResourceModel\Db\Collection类,包含以下事件:
core_collection_abstract_load_before $this->_eventPrefix . '_load_before' core_collection_abstract_load_after $this->_eventPrefix . '_load_after'
让我们仔细看看其中一个事件,该事件位于<MAGENTO_DIR>/framework/Model/AbstractModel.php文件中:
public function afterCommitCallback() { $this - > _eventManager - > dispatch('model_save_commit_after', ['object' => $this]); $this - > _eventManager - > dispatch($this - > _eventPrefix. '_save_commit_after', $this - > _getEventData()); return $this; } protected function _getEventData() { return ['data_object' => $this, $this - > _eventObject => $this, ]; }
$_eventPrefix和$_eventObject类型属性在这里特别重要。如果我们浏览Magento\Catalog\Model\Product、Magento\Datalog\Module\Category、
MagentoCustomer\Model\Customer、Magento \ Quote \ Model \ Quote等类型,
Magento\Sales\Model\Order等,我们可以看到,这些实体类型中有很多本质上是从Magento\Framework\Model\AbstractModel扩展而来的,
并提供了它们自己的值来取代$_eventPrefix=“core_abstract”和$_eventObject=“object”。
这意味着我们可以使用诸如$this->_eventPrefix'之类的事件_save_commit_after'通过events.xml指定观察者。让我们看一下以下示例,该示例取自<MAGENTO_DIR>/module downloadable/etc/events.xml文件:
<config> <event name="sales_order_save_commit_after"> <observer name="downloadable_observer" instance="Magento\Downloadable\Observer\SetLinkStatusObserver" /> </event> </config>
观察者被放置在<ModuleDir>/Observer目录中。每个观察者在Magento\Framework\Event\ObserverInterface类上实现一个单独的执行方法:
class SetLinkStatusObserver implements\ Magento\ Framework\ Event\ ObserverInterface { public function execute(\Magento\ Framework\ Event\ Observer $observer) { $order = $observer - > getEvent() - > getOrder(); } }
就像插件一样,实现不好的观察者很容易导致错误,甚至破坏整个应用程序。这就是为什么我们需要保持观测器的小型化和计算效率,以避免性能瓶颈。
周期性事件循环是一个很容易陷入的陷阱。当观察者在某个时刻调度其侦听的同一事件时,就会发生这种情况。
例如,如果观察者侦听model_save_before事件,然后试图在观察者中再次保存同一实体,这将触发循环事件循环。
为了使我们的观察者尽可能具体,我们需要在适当的范围内宣布他们:
对于只观察前端的事件,您可以在<ModuleDir>/etc/frontend/events.xml中声明观察者对于只观察后端的事件
可以在<ModuleDir>/etc/adminhtml/events.xml
为了观察全局事件,您可以在<ModuleDir>/etc/events.xml中声明观察者。与插件不同,观察者用于触发后续功能,
而不是更改作为其观察事件一部分的函数或数据的行为。