How to Create Plugin in Magento 2
As defined by the official document,
“A plugin or interceptor is a class that modifies the behavior of public class functions by intercepting a function call and running code before, after, or around that function call and allows to substitute or extend the behavior of original, public methods for any class or interface.”
Simplifying the words,
“A plugin or interceptor is a way to insert code dynamically without changing the original class behavior. It allows extending the core functionality without any modification to the core files.”
Hopefully, for beginners, the term “plugin” is not confused with the “module” as they are the synonyms for platforms like WordPress. But not in Magento!
Magento 1 allowed to customize different classes and methods by rewriting a class. Powerful, but in this way, no modules could rewrite the same class, and hence, no flexibility. To overcome the rewrite conflicts and instability, Magento 2 comes with inceptors or plugins! And, the post is everything about it from the reasons to use, its restrictions, types and the method to create plugin in Magento 2.
Why should you use Inceptors or Plugins in Magento 2?
- Minimum confliction among extensions that change the behavior of the same class or method
- Avoid collisions between plugins by using sort order attribute of plugin
- The plugin can be called sequentially according to sort order, so conflict with other plugin class can be avoided.
- No issue of rewriting the system
- Customize the same method in different modules
- Ability to modify the return value of any method call that is used on an object manager controlled object
- Ability to modify the arguments of any method call that is used on an object manager controlled object
However, it comes with limitations 🙁
The Magento 2 Plugins can’t be used with:
- Non-public methods
- Static methods
- Final Methods
- Final classes
- Virtual Types
- Any class that has at least one final public method
- Objects that are instantiated before Magento\Framework\Interception is bootstrapped
- __construct
Types of Inceptors in Magento 2:
-
Before listener
- Before listeners are used whenever we want to change the arguments of an original method or want to add some behavior before an original method is called.
- First methods to run in an observed method
- Before listener is called by adding the prefix ‘before’ to the method name and setting the first letter of original method to capital.
- It lets you modify the parameters that will be used.
- Syntax: beforeMethodname()
-
After listener
- After listeners are used whenever we want to change the arguments of an original method or want to add some behavior after an original method is called.
- Starts running after the observed method is finished
- After listener is called by adding the prefix ‘after’ to the method name and setting the first letter of original method to capital.
- It let you modify the output
- Responsible for editing the results of an observed method in the right way and must have a return value.
- Syntax: afterMethodname()
-
Around listener
- Inceptors run before and after the observed method.
- Allows overriding a method
- Used when you want to change both the arguments and the returned values of the observed method or add behavior before and after the observed method is called.
- Around listener is called by adding the prefix ‘around’ to the method name and setting the first letter of original method to capital.
- It must have a return value
- Syntax: aroundMethodname()
Steps to Create Plugin in Magento 2:
- Create registration.php file in app\code\[Vendor]\[Namespace]\
123456<?php\Magento\Framework\Component\ComponentRegistrar::register(\Magento\Framework\Component\ComponentRegistrar::MODULE,'[Vendor]_[Namespace]',__DIR__); - Create module.xml file in app\code\[Vendor]\[Namespace]\etc
1234<?xml version="1.0"?><config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"><module name="[Vendor]_[Namespace]" setup_version="1.0.0"/></config> - Create di.xml file in app\code\[Vendor]\[Namespace]\etc
123456<?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\Controller\Index\Index"><plugin name="restrictCartQuantity" type="[Vendor]\[Namespace]\Plugin\Checkout\Controller\RestrictProductQuantity"/></type></config> - Create RestrictProductQuantity.php in [Vendor]\[Namespace]\Plugin\Checkout\Controller
1234567891011121314<?phpnamespace [Vendor]\[Namespace]\Plugin\Checkout\Controller;class RestrictProductQuantity{public function aroundExecute(Index $subject,\Closure $proceed){//You required logic}}
Isn’t inceptor really a cool thing!
I’ve used this solution to configure TinyMCE4 toolbar in Magento 2.3.x versions.
With the above method, create plugin in Magento 2 easily.
Do not hesitate to use the Comments section below if you have any doubts with Magento 2 interceptors.
Thanks!
Sanjay Jethva
Sanjay is the co-founder and CTO of Meetanshi with hands-on expertise with Magento since 2011. He specializes in complex development, integrations, extensions, and customizations. Sanjay is one the top 50 contributor to the Magento community and is recognized by Adobe.
His passion for Magento 2 and Shopify solutions has made him a trusted source for businesses seeking to optimize their online stores. He loves sharing technical solutions related to Magento 2 & Shopify.
2 Comments
why we are using ‘\closure $proceed’ argument over ‘callable $proceed’ argument in the arountExecute method?
Hello Samir,
The Closure must be an anonymous function, whereas callable can be a normal function.
if you only want to type-hint anonymous function, use: Closure and if you want also to allow normal functions, use callable
Thank You