M2 preference和plugin的使用
M2 preference和plugin的使用
preference类似于Magento 1中的类重写,等同于说用B类重写A类,我们可以在B类上添加或修改。每当任何类请求类A的实例时,它将随类B实例一起提供。在这里,B类是A类的重写类。基本上,B类包括A类的业务逻辑,可以对其进行扩展或修改。
在di.xml中进行配置,下面是重写MagentoCheckoutControllerOnepageFailure的实例:
在di.xml中声明preference
<!--preference(重写前的类);type(重写后的类)--> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="MagentoCheckoutControllerOnepageFailure" type="vendorNameCheckoutControllerOnepageFailure" /> </config>
<?php namespace vendorNameCheckoutControllerOnepage; class Failure extends MagentoCheckoutControllerOnepageFailure { }
plugin是Magento 2中新引入的,允许我们在插入该类的任何公共方法之前,之后和周围执行我们的代码,我们的plugin会钩入。plugin不会覆盖该类。相反,它挂接到我们要修改业务逻辑的类的各个方法中。plugin通常会避免在覆盖类时出现的冲突。
什么情况Magento 2 Interception插 plugin无法使用?
- 在Magento Framework Interception之前实例化的对象是自我引导运行的;
- 最后的方法;
- 最后的类;
- 任何包含至少一个最终公共方法的类;
- 非 Public 方法(Non-public methods);
- 类方法(如静态方法);
- __construct;
- 虚拟类型(Virtual types);
在 di.xml中声明一个plugin
<config> <type name="{ObservedType}"> <plugin name="{pluginName}" type="{PluginClassName}" sortOrder="1" disabled="false"/> </type> </config>
必需的选项:
type name:输入需要遵循的类或接口的名称。
plugin name:标识plugin的任意plugin名称。还用于合并plugin的配置。
plugin type:填写plugin类的名称或其虚拟类型。您可以为此字段引用以下命名约定:VendorModulePlugin<ModelName>Plugin。
可选选项:
plugin sortOrder:当plugin调用进程中的其他相同方法时设置顺序。
plugin disabled:这允许您快速启用或禁用plugin。作为默认配置,所选值为false。使用此属性可禁用di.xml文件中的核心或第三方plugin。
plugin中的3种方法:
1. before - beforeDispatch() --在观察到的方法开始之前运行,并且这些方法必须与观察到的名称具有相同的名称,而前缀标签是“before”
2. around - aroundDispatch() --around方法允许代码在observe方法之前和之后运行,因此您可以覆盖方法。这些方法必须与观察到的名称具有相同的名称,而前缀标签为“around”
3. after - afterDispatch() --在观察到的方法完成后立即开始运行,并且这些方法必须与观察到的名称具有相同的名称,而前缀标签是“after”
如下例所示,我们将编辑 appcodeSamaryHelloWorldetcdi.xml, 定义一个plugin
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> <type name="SamaryHelloWorldControllerIndexExample"> <plugin name="Samary_HelloWorld_Plugin" type="SamaryHelloWorldPluginExamplePlugin" sortOrder="10" disabled="false" /> </type> </config>
例如,下面的代码定义了类型名称,我们在 app/code/Samary/HelloWorld/Controller/Index/ /创建了Example.php文件
<?php namespace SamaryHelloWorldControllerIndex; class Example extends MagentoFrameworkAppActionAction { protected $title; public function execute() { echo $this->setTitle('Welcome'); echo $this->getTitle(); } public function setTitle($title) { return $this->title = $title; } public function getTitle() { return $this->title; } }
使用plugin名称,我们在 app/code/Samary/HelloWorld/Plugin/ 创建了Example.php文件:
<?php namespace SamaryHelloWorldPlugin; class ExamplePlugin { public function beforeSetTitle(SamaryHelloWorldControllerIndexExample $subject, $title) { $title = $title . " to "; echo __METHOD__ . "</br>"; return [$title]; } public function afterGetTitle(SamaryHelloWorldControllerIndexExample $subject, $result) { echo __METHOD__ . "</br>"; return '<h1>'. $result . 'samary.cn' .'</h1>'; } public function aroundGetTitle(SamaryHelloWorldControllerIndexExample $subject, callable $proceed) { echo __METHOD__ . " - Before proceed() </br>"; $result = $proceed(); echo __METHOD__ . " - After proceed() </br>"; return $result; } }
区别:
plugin是一个类,它通过拦截函数调用并在该函数调用之前,之后或周围运行代码来修改公共类函数的行为。这使您可以替换或扩展任何类或接口的原始公共方法的行为。这种拦截方法减少了扩展之间的冲突,这些扩展改变了相同类或方法的行为。您的Plugin类实现会更改类函数的行为,但不会更改类本身。Magento根据配置的排序顺序依次调用这些拦截器,因此它们不会相互冲突。
preference用于覆盖类.
注:plugin比preference更方便,除非有必要,否则应该在需要时选择使用plugin。