У Magento 2 з’явились плагіни-перехоплювачі (Magento 2 plugins, Magento 2 interceptors), які дозволяють виконати власний код до/після та навколо виклику публічного методу класу.
Зміст [приховати]
Наприклад, є клас PHP з відкритими функціями "setName", "getName", "save":
<?php
namespace VendorName\ModuleName\Folder;
class SomeModel
{
private $name;
public function setName($name, $storeId = 0) {
$this->name[0] = $name;
}
public function getName($storeId = 0) {
return $this->name[$storeId];
}
public function save($fields, $customData) {
/* some save logic here */
}
}
Як створити плагін в Magento 2?
1. Створіть файл etc/di.xml у папці вашого модуля, помістивши у нього код:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="VendorName\ModuleName\Foder\SomeModel">
<plugin name="mycompany_mymodule_plugin_modulename_foder_somemodel"
type="MyCompany\MyModule\Plugin\ModuleName\Foder\SomeModelPlugin" sortOrder="10" />
</type>
</config>
VendorName\ModuleName\Foder\SomeModel - назва класу, до методу (методів) якого задіюватиметья плагін;
mycompany_mymodule_plugin_modulename_foder_somemodel - унікальна назва вашого плагіна, формуйте її із назви класу плагіна;
MyCompany\MyModule\Plugin\ModuleName\Foder\SomeModel - клас плагіна;
sortOrder - задає пріоритет виконання вашого плагіну, серед інших плагінів для цього класу.
Увага! Файл di.xml можна створенити у папці "etc" і в "ect/frontend", "etc/adminhtml" і тп., залежно від зони застосовування.
2. Створіть файл Plugin/ModuleName/Folder/SomeModelPlugin.php для класу перехоплювача; MyCompany\MyModule\Plugin\ModuleName\Foder\SomeModelPlugin у папці модуля.
3. Помістіть у нього код:
<?php
namespace MyCompany\MyModule\Plugin\ModuleName\Folder;
use \VendorName\ModuleName\Foder\SomeModel;
class SomeModelPlugin
{ public function beforeSetName(SomeModel $subject, $name)
{
return ['(' . $name . ')'];
}
public function afterGetName(SomeModel $subject, $result)
{
return '|' . $result . '|';
}
public function aroundSave(SomeModel $subject, callable $proceed, $arg1, $arg2) {
if ($arg1 && subject->someTerm()){
return $proceed($arg1, $arg2);
}
return null;
}
}
Magento 2 Before Plugin
Before plugin використовується для зміни вхідних даних вихідної функції (setName).
Ім’я функції складається зі слова «before» плюс оригінальна назва функції з великої першої літери, наприклад: before + SetName = beforeSetName.
Першим вхідним аргументом є $subject - вихідний об'єкт класу, наступні вхідні параметри вихідної функції.
Функція плагіна повертає масив змінених вхідних параметрів (arguments). Порядок елементів результату в масиві повинен відповідати порядку вхідних аргументів. Якщо ви не хочете змінювати аргументи, а просто запустити якийсь код перед виконанням оригінальної функції, то функція плагіна повинна поверне нульове значення (null value).
Magento 2 After Plugin
After plugin використовується для зміни вихідного результату функції або дозволяє запускати код після виконання оригінальної функції (getName).
Ім’я функції складається зі слова «after» плюс оригінальна назва функції з великої першої літери, наприклад: after + GetName = afterGetName.
Першим вхідним аргументом є $subject - оригінальний об'єкт класу, другим є - $result - результат вихідної функції або плагінів, які були виконані раніше через пріоритет порядку сортування, наступні вхідні параметри вихідної функції.
Функція плагіна повертає новий результат.
Важливо!
Якщо ви не хочете змінювати результат, а просто запустити якийсь код після виконання початкової функції, ви НЕ МОЖЕТЕ повернути нульове значення (null value), як це було з плагіном «before», оскільки повертаючи null, ви активно змінюєте результат на NULL . Не пропустіть це.
Magento 2 Around Plugin
Around plugin - змінює вихідний результат функції на основі вхідних даних або вимикає виконання вихідної функції (save).
Це небезпечно.
Magento рекомендує уникати використання плагінів around, якщо вони не потрібні, оскільки їх використання може перешкодити виконанню оригінальної функції або інших плагінів у черзі, а також збільшити трасування стека (stack traces) та вплинути на продуктивність.
Плагіни around були корисними до випуску Magento 2.2, оскільки раніше цієї версії плагінам «after» не дозволялося отримувати аргументи функції введення. Плагін around в основному використовувався для зміни результату на основі вхідних аргументів.
Ім’я функції складається зі світу «навколо» плюс оригінальна назва функції з великої першої літери, наприклад: around + Save = aroundSave.
Першим вхідним аргументом є $subject - оригінальний об'єкт класу, другий - $proceed - змінна, що дозволяє виконувати оригінальну функцію та інші плагіни в черзі, наступні вхідні параметри вихідної функції.
Функція around повертає новий результат.
Важливо!
Якщо функція $proceed() не буде виконана, стандартний код, а також плагіни з нижчим пріоритетом не будуть увімкнені.
Компіляція залежностей
Після завершення написання плагіна, не забудьте перегенерувати залежності ін'єкцій (Dependency injection). Виконайте команду:
php bin/magento setup:di:compile
Пам'ятайте, що плагіни не можуть бути застосованими до:
- фінальних методів;
- фінальних класів;
- не публічних методів;
- статичних методів;
- конструктора;
- віртуальних типів;
- об'єктів, які ініціалізуються перед загрузкою плагінів;
Після того, як ви створите плагіни у Magento 2, вам потрібно задати їм пріоритети, щоб визначити який з них викликати, якщо підходить більше ніж один плагін.