The very first thing is, don’t confuse it with the “module”, since modules are called plugins in some platforms, for example, WordPress. In this case, the plugin is a part of a module that is used for intercepting a function call in Magento.
A plugin, or interceptor, is a whole new concept introduced in Magento 2. In Magento 1, to customize different classes and methods, you would have to rewrite a class. This was a very powerful way of customization but with a cost of flexibility as no two modules could rewrite the same class. In addition, rewrite conflicts created a lot of instability in the Magento 1 platform.
Magento 2 created a new customization method to remedy this issue, called a plugin or interceptor.
A plugin, or an interceptor, is a class that modifies the behavior of public class functions by intercepting a function call and running the code before, after, or around that function’s call. This allows you to substitute or extend the behavior of the original, public methods for any classes or interfaces. Actually, there is a design pattern named “Interception” used in plugins. So, an interception in technical terms means “inserting code dynamically without changing the original class behavior”, which is exactly what a plugin does in Magneto 2.
There are several main reasons for using plugins:
Plugins can’t be used with any of the following:
In Magento 2, we can create and use three types of Plugins:
Before listeners are used to change the arguments of an original method or to add some behavior before an original method is called.
Before listener is called by adding the prefix ‘before’ to the method name and setting the first letter of the original method to capital.
Prototype: beforeMethodname()
Example: beforeAddProduct()
Original Method: public function addProduct(<ARGUMENTS>)
Plugin Method: public function beforeAddProduct(<ARGUMENTS>)Note: The “before listener” methods don’t need to have a return value.
After listeners are used to change the values returned by the original method or to add some behavior after the original method is called.
After listener is called by adding a prefix after the method name and capitalizing the first letter of the original method.
Prototype: afterMethodname()
Example: afterGetName()
Original Method: public function getName(<ARGUMENTS>)
Plugin Method: public function afterGetName(<ARGUMENTS>)Note: The after listener methods do not need to have a return value.
By definition, the code of the Around methods is run both before and after the observed method. This allows you to completely override a method. The after plugin is used to change both the arguments and the returned values of the original method or to add some behavior before and after the original method is called.
Around listener is called by adding a prefix around the method name and capitalizing the first letter of the original method.
Prototype: aroundMethodname()
Example: aroundAddProduct()
Original Method: public function addProduct(<ARGUMENTS>)
Plugin Method: public function aroundAddProduct(<ARGUMENTS>)
Note: The around listener methods must have a return value.
To use plugins, first of all, we have to define it in di.xml.
<config> <type name="{ObservedType}"> <plugin name="{pluginName}" type="{PluginClassName}" sortOrder="1" disabled="false"/> </type> </config>
Explanation
Required elements:
There are three elements required.
Type name: A class, an interface, or a virtual type, which is observed by a plugin.
Plugin name: An arbitrary plugin name that identifies a plugin.
Plugin type: The name of a plugin’s class or its virtual type. Use the following naming convention when specifying this element: \Vendor\Module\Plugin\<ModelName>Plugin.
Optional elements:
These two elements are optional
Plugin sortOrder: The order in which plugins that call the same method are run.Plugin disabled: To disable a plugin, set this element to true. The default value is false.
Now we will create a plugin class that you define in di.xml as type= “{PluginClassName}” and will use before, after or around the method as per our need. For example:-
<?php namespace Vendor\Module\Plugin; class ExamplePlugin{ }
Let us create some plugins so we can understand all types of plugins.
In this example, we will change qty to 5 so that it always adds 5 quantities of product whenever we add to the cart.
<?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\Checkout\Model\Cart"> <plugin name="exampleofbefore" type="Bizspice\Beforelistener\Plugin\Cart" sortOrder="1" /> </type> </config>
<?php namespace Bizspice\Beforelistener\Plugin; class Cart { public function beforeAddProduct( \Magento\Checkout\Model\Cart $subject, $productInfo, $requestInfo = null ) { $requestInfo['qty'] = 5; // increasing quantity to 10 return array($productInfo, $requestInfo); } }
In this example, we will change the product price that will be reflected everywhere on the website including the list page, product page, cart page, and order page.
<config> <type name="Magento\Catalog\Model\Product"> <plugin name="change_product" type=" Bizspice\Afterlistener\Plugin\Product " sortOrder="1" /> </type> </config>
<?php namespace Bizspice\Afterlistener\Plugin; class Product { public function afterGetPrice(\Magento\Catalog\Model\Product $subject, $result) { return $result*2; } }
<config> <type name="Magento\Catalog\Model\Product"> <plugin name="change_cart" type=" Bizspice\Aroundlistener\Plugin\Cartplugin " sortOrder="1" /> </type> </config>
<?php namespace Bizspice\Afterlistener\Plugin; class Cartplugin { public function aroundAddProduct(\Magento\Checkout\Model\Cart $subject,$proceed){ // before adding product to cart $productId = (int)$this->request->getParam('product', 0); $qty = (int)$this->request->getParam('qty', 1); // this will run the core addProduct function $returnValue = $proceed(); // below code is executed after product is added to cart if ($returnValue) { // after adding product to cart } return $returnValue; } }