In Magento 2 version, developers have a new possibility to extend or change the behavior of any public method within a core class through Plugins(Interceptors), that is based on Interceptor design pattern.
Interceptor classes are generated dynamically and can be found in generated/code folder. They extend the original classes but wrap its methods to allow a plugin to be called before, after or instead of a required method.
So there are three types of plugins: before, after and around.
Before plugins
We should use these plugins Magento in order to modify the arguments passed to the original method or add some behavior before the method is called.
Let’s create before plugin. For example, we need to log password changing. We will create a plugin for the changePassword method of Magento\Customer\Model\AccountManagement class.
1. To di.xml add the following code:
1 2 3 4 5 6 | <?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="Magento\Customer\Model\AccountManagement"> <plugin name="logChangePassword" type="MageDirect\Test\Plugin\Model\LogChangePassword" sortOrder="1"/> </type> </config> |
We must define required arguments:
- type name: a class, interface, or virtual type that the plugin observes
- plugin name: an arbitrary name that identifies the plugin; used to merge the configurations for the plugin
- plugin type: the name of a plugin class or its virtual type; uses the naming convention <ModelName>\Plugin
The following arguments are optional:
- plugin sortOrder: the order in which plugins that call the same method are run
- plugin disabled: set to TRUE to disable a plugin
2. Create MageDirect\Test\Plugin\Model\LogChangePassword class and enter the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?php namespace MageDirect\Test\Plugin\Model; use Psr\Log\LoggerInterface as PsrLogger; class LogChangePassword { /** * @var PsrLogger */ protected $logger; /** * @param PsrLogger $logger */ public function __construct(PsrLogger $logger) { $this->logger = $logger; } /** * @param \Magento\Customer\Model\AccountManagement $subject * @param string $email * @param string $currentPassword * @param string $newPassword */ public function beforeChangePassword(\Magento\Customer\Model\AccountManagement $subject, $email, $currentPassword, $newPassword) { $this->logger->info(__('Trying to change password for %1', $email)); } } |
Notice that we name our method as before{methodName}. If we want after(around) plugin, it should be after{methodName}(around{methodName}).
3. Clean cache:
1 | php bin/magento cache:clean config |
4. In generated/code/Magento/Customer/Model/AccountManagement/ folder we can see Interceptor class and changePassword method:
1 2 3 4 5 6 7 8 9 10 11 12 | /** * {@inheritdoc} */ public function changePassword($email, $currentPassword, $newPassword) { $pluginInfo = $this->pluginList->getNext($this->subjectType, 'changePassword'); if (!$pluginInfo) { return parent::changePassword($email, $currentPassword, $newPassword); } else { return $this->___callPlugins('changePassword', func_get_args(), $pluginInfo); } } |
All plugins are called in the ___callPlugins method of \Magento\Framework\Interception\Interceptor.
After plugins
After plugins are used whenever we want to change the returned result or add some behavior after the method is called.
Here is an example of after plugin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | namespace MageDirect\Test\Plugin\Block; class ReplaceCopyright { /** * @param \Magento\Theme\Block\Html\Footer $subject * @param string $result * @return string */ public function afterGetCopyright(\Magento\Theme\Block\Html\Footer $subject, $result) { return sprintf("%s (c) MageDirect. All rights reserved.", date('Y')); } } |
And di.xml:
1 2 3 4 5 6 7 | <?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="Magento\Theme\Block\Html\Footer"> <plugin name="replaceCopyright" type="MageDirect\Test\Plugin\Block\ReplaceCopyright" sortOrder="1"/> </type> </config> |
In this example, we have changed the returned value of the getCopyright method.
Around plugins
Around plugins can be used when we want to change both the arguments and the returned values of an original method or add some behavior before and after an original method is called.
Let’s take a look at an example of around plugin, that log info before and after add item to wishlist.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <?php namespace MageDirect\Test\Plugin\Model; use Psr\Log\LoggerInterface as PsrLogger; class LogWishlist { /** * @var PsrLogger */ protected $logger; /** * @param PsrLogger $logger */ public function __construct(PsrLogger $logger) { $this->logger = $logger; } /** * @param \Magento\Wishlist\Model\Wishlist $subject * @param \Closure $proceed * @return \Magento\Wishlist\Model\Wishlist */ public function aroundAddItem(\Magento\Wishlist\Model\Wishlist $subject, \Closure $proceed, ...$args) { $this->logger->info(__('Before add to withlist')); $result = $proceed(...$args); $this->logger->info(__('After add to withlist')); return $result; } } |
1 2 3 4 5 6 7 | <?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="Magento\Wishlist\Model\Wishlist"> <plugin name="logAddToWishlist" type="MageDirect\Test\Plugin\Model\LogWishlist" sortOrder="1" /> </type> </config> |
More information
More info in the official documentation:
- http://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html
- http://devdocs.magento.com/guides/v2.0/extension-dev-guide/code-generation.html
Still have questions? Ask MageDirect experts about Magento consulting. Develop your business in a fast and efficient way.
Lilya GogolevaMagento Developer
- Follow this tutorial to clear Magento cache with no efforts. Also, you will...
- This easy and effortless tutorial on how to create the new admin account in...
- If you don’t know how to create a custom cache type in Magento, this article...
- SSL is very important for every online store as it initiates a secure session...
- The sitemap is highly important in case you want to optimize your website for...
- Want to manage email templates in your Magento 2 store? Check our article and...
- Do you know how to create custom product type? We know! And would be glad to...
- Want to have a Magento 2 Multistore? Read how our team setups...