Magento 2插件是一个技术插件,可以更好地编写代码。拦截插件被称为一个小的 magento 2扩展,它允许通过在函数调用之前或之后拦截函数调用和运行代码来编辑任何公共类或方法的行为。通过使用此 Magento 2插件拦截,您可以修改类的行为,而无需直接更改类。
目录
- Magento 2插件的好处
- Magento 2插件的限制
- 创建Magento 2新插件的指南
- 在Magento 2中声明一个插件
- 解释相关
- 在Magento 2中定义一个插件
- 之前的方法
- 方法之后
- 围绕方法
- 检查结果
- 设置插件的优先级
- Magento 2插件示例
也许你仍然认为观察者可以帮助你流利地做到这一点,但需要指出一些差异。特别是,不仅使用依赖注入创建类的函数,而且还可以使用sortOrder确认Interception插件,该sortOrder允许检查链接和运行插件的顺序。这就是为什么这个插件不会使类更改并且彼此之间没有任何冲突的原因
Magento 2插件的好处
对于像您一样的模块开发人员,Magento 2 Interception插件允许:
- 转发在对象管理器控制的对象上使用的任何方法调用并采取编程操作
- 修改在对象管理器控制的对象上使用的任何方法调用的返回值
- 修改在对象管理器控制的对象上使用的任何方法调用的参数
- 当其他模块以相同或可预测的方式进行相同方法时,类似地继续进行。
如果您从未有过以这种方式创建系统的经验,那么当您对性能特征感到困惑时,并不奇怪。
Magento 2插件的限制
Magento 2 Interception插件有哪些选项不兼容?
- 之前实例化的对象
Magento\Framework\Interception
是自举的 - 最后的方法
- 最后的课程
- 任何包含至少一个最终公共方法的类
- 非公开方法
- 类方法(如静态方法)
__construct
- 虚拟类型
创建Magento 2新插件的指南
在Magento 2中声明一个插件
为类对象设置新插件时,它将在di.xml
文件中定义app/code/{namespace}/{module}/etc/di.xml
。
<config>
<type name="{ObservedType}">
<plugin name="{pluginName}" type="{PluginClassName}" sortOrder="1" disabled="false"/>
</type>
</config>
解释相关
必需的选项
type name
:输入需要遵循的类或接口的名称。plugin name
:标识插件的任意插件名称。还用于合并插件的配置。plugin type
:填写插件类或其虚拟类型的名称。您可以为此字段引用以下命名约定:\Vendor\Module\Plugin\<ModelName>Plugin
。
可选选项
plugin sortOrder
:当插件调用进程中的其他相同方法时设置顺序。plugin disabled
:这允许您快速启用或禁用插件。作为默认配置,所选值为false
。使用此属性可禁用文件中的核心或第三方插件di.xml
。
如下例所示,我们将进行编辑app\code\Mageplaza\HelloWorld\etc\di.xml
,您需要插入代码段:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Mageplaza\HelloWorld\Controller\Index\Example">
<plugin name="Mageplaza_HelloWorld_Plugin" type="Mageplaza\HelloWorld\Plugin\ExamplePlugin" sortOrder="10" disabled="false" />
</type>
</config>
例如,以下代码定义了类型名称,我们在其中创建了Example.php
文件app/code/Mageplaza/HelloWorld/Controller/Index/
内容如下:
<?php
namespace Mageplaza\HelloWorld\Controller\Index;
class Example extends \Magento\Framework\App\Action\Action
{
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;
}
}
使用插件名称,我们创建了Example.php
文件app/code/Mageplaza/HelloWorld/Plugin/
内容如下:
<?php
namespace Mageplaza\HelloWorld\Plugin;
class ExamplePlugin{
}
在Magento 2中定义一个插件
插件是通过在方法之前,之后或周围使用代码来扩展或编辑公共方法行为的好方法。
首先,请获取一个对象,该对象提供对被观察方法类的所有公共方法的许可。
插件中的3种方法
before
-beforeDispatch()
around
-aroundDispatch()
after
-afterDispatch()
之前的方法
在方法是在观察方法中运行的第一种方法之前,这些方法必须与前面标签所在的观察名称具有相同的名称before
。
要应用before方法来修改观察方法的参数,可以返回修改后的参数。如果有多个参数,则返回将根据这些参数的范围执行。如果返回无效,则意味着不应修改被观察方法的参数。
<?php
namespace Mageplaza\HelloWorld\Plugin;
class ExamplePlugin
{
public function beforeSetTitle(\Mageplaza\HelloWorld\Controller\Index\Example $subject, $title)
{
$title = $title . " to ";
echo __METHOD__ . "</br>";
return [$title];
}
}
方法之后
方法在观察到的方法完成后立即开始运行,并且这些方法必须与观察到的名称具有相同的名称,而前缀标签是“after”。
在方法之后,负责以正确的方式编辑观察方法的结果,并且需要具有返回值。
<?php
namespace Mageplaza\HelloWorld\Plugin;
class ExamplePlugin
{
public function afterGetTitle(\Mageplaza\HelloWorld\Controller\Index\Example $subject, $result)
{
echo __METHOD__ . "</br>";
return '<h1>'. $result . 'Mageplaza.com' .'</h1>';
}
}
围绕方法
around方法允许代码在observe方法之前和之后运行,因此您可以覆盖方法。这些方法必须与观察到的名称具有相同的名称,而前缀标签为“around”。
在安排原始方法的参数之前,将callable
围绕方法调用链中的下一个方法,这意味着也会调用下一个插件或观察到的函数。
注意:如果callable
未声明,则不会调用下一个插件和原始方法。
<?php
namespace Mageplaza\HelloWorld\Plugin;
class ExamplePlugin
{
public function aroundGetTitle(\Mageplaza\HelloWorld\Controller\Index\Example $subject, callable $proceed)
{
echo __METHOD__ . " - Before proceed() </br>";
$result = $proceed();
echo __METHOD__ . " - After proceed() </br>";
return $result;
}
}
检查结果
所有内容 ExamplePlugin.php
<?php
namespace Mageplaza\HelloWorld\Plugin;
class ExamplePlugin
{
public function beforeSetTitle(\Mageplaza\HelloWorld\Controller\Index\Example $subject, $title)
{
$title = $title . " to ";
echo __METHOD__ . "</br>";
return [$title];
}
public function afterGetTitle(\Mageplaza\HelloWorld\Controller\Index\Example $subject, $result)
{
echo __METHOD__ . "</br>";
return '<h1>'. $result . 'Mageplaza.com' .'</h1>';
}
public function aroundGetTitle(\Mageplaza\HelloWorld\Controller\Index\Example $subject, callable $proceed)
{
echo __METHOD__ . " - Before proceed() </br>";
$result = $proceed();
echo __METHOD__ . " - After proceed() </br>";
return $result;
}
}
在此之后,请清除缓存并检查结果。它会像这样显示出来
如果您的插件由与参数匹配的方法调用,它也必须与它们匹配,同时,您需要仔细遵循它们。在此过程中,请注意方法的原始签名以及默认参数和建议类型。
例如,应用以下代码来标识SomeType类型的参数,即nullable
:
<?php
namespace Mageplaza\HelloWorld\Model;
class MyUtility
{
public function save(SomeType $obj = null)
{
//do something
}
}
如果你用下面的插件包装这个方法:
<?php
namespace Mageplaza\HelloWorld\Plugin;
class MyUtilityPlugin
{
public function aroundSave(\Mageplaza\HelloWorld\Model\MyUtility $subject, \callable $proceed, SomeType $obj)
{
//do something
}
}
注意:缺少=空
如果您将该方法与null一起调用,则PHP会产生致命错误,因为您的插件中不允许使用插件null。此外,遵循方法调用的插件中的参数非常重要。但如果不关心参数,请使用variadics和参数解包来完成此操作:
<?php
namespace Mageplaza\HelloWorld\Plugin;
class MyUtilityPlugin
{
public function aroundSave(\Mageplaza\HelloWorld\Model\MyUtility $subject, \callable $proceed, ...$args)
{
//do something
$proceed(...$args);
}
}
设置插件的优先级
sortOrder
选项允许将观察相同方法的插件放入队列中。当方法开始调用之前,之后或周围时,插件将逐个应用。
Magento 2插件示例
访问https://github.com/mageplaza/magento2-samples/tree/master/sample-module-interception