Plugins in Magento 2 are like secret agents — they step in, tweak behaviour, and vanish without leaving a trace. Whether you’re a beginner looking to understand how plugins work or an expert refining your customizations, this guide will help you master Magento 2 plugins without breaking a sweat. Let’s dive in and unleash the power of interceptors!
What Are Plugins in Magento 2?
Plugins, also known as interceptors, allow you to modify or extend the behaviour of public methods in Magento 2 classes without overriding them. This ensures maximum compatibility and reduces the risk of breaking core functionalities.
Before learning about plugins, it’s important to understand the idea of interception. In Magento, these two terms are often used together.
Interception is a way to add extra code without changing the original class. It works by putting the new code between the calling code and the target object.
Magento uses plugins to apply the interception pattern. Plugins let you add code using before, after, and around methods, so you can change or extend what a method does without directly editing it.
Limitations of Plugins
Plugins cannot be created for just any class or method, as they do not work for the following:
- Final methods/classes
- Non-public methods (protected or private)
- Static methods that are created without a dependency injection
- Constructor ( _construct)
- Virtual Types
Types of Plugins
Think of them as filters that can:
- Before Method: Execute logic before the original method.
- The before listeners are used when we want to change the arguments of an original method or add some behaviour before an original method is called.
- After Method: Execute logic after the original method.
- The after listeners are used when we want to change the values returned by an original method or add some behaviour after an original method is called.
- Around Method: Wrap around the original method to control its execution.
- The around listeners are used when we want to change both the arguments and the returned values of an original method or add some behaviour before and after an original method is called.
When to Use Plugins?
- Modify core or third-party module behaviour safely.
- Add custom logic without altering the original class.
- Avoid class rewrites, making upgrades easier.
Pro Tip: Plugins are ideal for altering methods with low dependencies. Avoid using them on getters, setters, or magic methods.
Creating a Plugin in Magento 2
Here’s how you can create a simple plugin in Magento 2.
Scenario: Let’s add custom logic before a product name is returned in the product repository.
Defining the plugins in di.xml
Plugins are created in the di.xml
file of the module. It is possible to use the global from etc/ or the area specific from etc/[area]; in this case, we will use the global, which means that it is used in all areas.
<?xml version="1.0"?>
<!--
/**
* Copyright © Jigar Karangiya. All rights reserved.
*
* Blog : Mastering Plugins in Magento 2: A Beginner-to-Expert Guide
* File : app/code/Jigar/PluginsTutorial/etc/di.xml
* Visit https://jigarkarangiya.com/mastering-plugins-in-magento-2-a-beginner-to-expert-guide/ for more details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Catalog\Api\ProductRepositoryInterface">
<!-- Plugin for after method -->
<plugin name="jigar_after_plugin_example"
type="Jigar\PluginsTutorial\Rewrite\Magento\Catalog\Api\ProductRepositoryInterfaceAfterPlugin"
disabled="false"
sortOrder="100"/>
<!-- Plugin for before method -->
<plugin name="jigar_before_plugin_example"
type="Jigar\PluginsTutorial\Rewrite\Magento\Catalog\Api\ProductRepositoryInterfaceBeforePlugin"
disabled="false"
sortOrder="200"/>
<!-- Plugin for around method -->
<plugin name="jigar_around_plugin_example"
type="Jigar\PluginsTutorial\Rewrite\Magento\Catalog\Api\ProductRepositoryInterfaceAroundPlugin"
disabled="false"
sortOrder="300"/>
</type>
</config>
Plugins are set up in the module’s di.xml
file. To create a plugin, you use the type
element with its name
attribute to link it to the class you want to observe.
In the type
element, you can define one or more plugins using the plugin
element. The plugin
element has four main attributes:
- name: A unique name to identify the plugin.
- sortOrder: Sets the order in which plugins run if multiple plugins observe the same method.
- disabled: By default, this is
false
. If set totrue
, the plugin will be turned off. - type: Refers to the class where you write the logic for the before, after, or around methods.
Using the after listener
An after
plugin allows you to execute custom code after the original method is called. This type of plugin can modify the result returned by the original method.
Example:
<?php
/**
* Copyright © Jigar Karangiya. All rights reserved.
*
* Blog : Mastering Plugins in Magento 2: A Beginner-to-Expert Guide
* Snippet : https://jigarkarangiya.com/mastering-plugins-in-magento-2-a-beginner-to-expert-guide/#Using_the_after_listener
*/
namespace Jigar\PluginsTutorial\Rewrite\Magento\Catalog\Api;
/**
* Class ProductRepositoryInterfaceAfterPlugin
*/
class ProductRepositoryInterfaceAfterPlugin
{
/**
* @param \Magento\Catalog\Api\ProductRepositoryInterface $subject
* @param \Magento\Catalog\Api\Data\ProductInterface $result
* @return \Magento\Catalog\Api\Data\ProductInterface
*/
public function afterGetById(
\Magento\Catalog\Api\ProductRepositoryInterface $subject,
$result
) {
// Add your custom logic here
$result->setName($result->getName() . ' - Modified by After Plugin');
return $result;
}
}
When you call the getById method of the ProductRepositoryInterface, the plugin will modify the product name by appending ” – Modified by After Plugin”.
<?php
$productRepository = $objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);
$product = $productRepository->getById($productId);
echo $product->getName(); // This will output the product name with " - Modified by After Plugin" appended.
Using the before listener
A before
plugin allows you to execute custom code before the original method is called. This type of plugin can modify the arguments passed to the original method.
Example:
<?php
/**
* Copyright © Jigar Karangiya. All rights reserved.
*
* Blog : Mastering Plugins in Magento 2: A Beginner-to-Expert Guide
* Snippet : https://jigarkarangiya.com/mastering-plugins-in-magento-2-a-beginner-to-expert-guide/#Using_the_before_listener
*/
namespace Jigar\PluginsTutorial\Rewrite\Magento\Catalog\Api;
/**
* Class ProductRepositoryInterfaceBeforePlugin
*/
class ProductRepositoryInterfaceBeforePlugin
{
/**
* Before get by ID
*
* @param \Magento\Catalog\Api\ProductRepositoryInterface $subject
* @param int $productId
* @param bool $editMode
* @param int|null $storeId
* @param bool $forceReload
* @return array
*/
public function beforeGetById(
\Magento\Catalog\Api\ProductRepositoryInterface $subject,
$productId,
$editMode = false,
$storeId = null,
$forceReload = false
) {
// Add your custom logic here
// For example, log the product ID
\Magento\Framework\App\ObjectManager::getInstance()
->get(\Psr\Log\LoggerInterface::class)
->info('Before GetById: ' . $productId);
// Return the modified arguments if needed
return [$productId, $editMode, $storeId, $forceReload];
}
}
The beforeGetById method is executed before the getById method of the ProductRepositoryInterface is called. You can add any custom logic here.
For example, i have added log to print the product ID, Check the below example for testing the plugin.
<?php
$productRepository = \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);
$product = $productRepository->getById(1); // Replace 1 with a valid product ID
Check the logs to see the output from your plugin.
Using the around listener
An around
plugin allows you to completely control the execution of the original method. You can decide whether to call the original method or not, and you can modify both the arguments and the result.
Example:
<?php
/**
* Copyright © Jigar Karangiya. All rights reserved.
*
* Blog : Mastering Plugins in Magento 2: A Beginner-to-Expert Guide
* Snippet : https://jigarkarangiya.com/mastering-plugins-in-magento-2-a-beginner-to-expert-guide/#Using_the_around_listener
*/
namespace Jigar\PluginsTutorial\Rewrite\Magento\Catalog\Api;
use Magento\Catalog\Api\ProductRepositoryInterface;
/**
* Class ProductRepositoryInterfaceAroundPlugin
*/
class ProductRepositoryInterfaceAroundPlugin
{
/**
* @param ProductRepositoryInterface $subject
* @param \Closure $proceed
* @param $productId
* @param bool $editMode
* @param null $storeId
* @param bool $forceReload
* @return mixed
*/
public function aroundGetById(
ProductRepositoryInterface $subject,
\Closure $proceed,
$productId,
$editMode = false,
$storeId = null,
$forceReload = false
) {
// Before plugin logic
// For example, logging the product ID
\Magento\Framework\App\ObjectManager::getInstance()
->get(\Psr\Log\LoggerInterface::class)
->info('Before GetById: ' . $productId);
// Proceed to the original method
$result = $proceed($productId, $editMode, $storeId, $forceReload);
// After plugin logic
// For example, modifying the result
$result->setName($result->getName() . ' - Modified by Around Plugin');
return $result;
}
}
You can create a simple script or a test class that calls the getById method of the ProductRepositoryInterface to test the plugin.
<?php
use Magento\Framework\App\Bootstrap;
use Magento\Framework\App\ObjectManager;
use Magento\Catalog\Api\ProductRepositoryInterface;
require __DIR__ . '/app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$objectManager = $bootstrap->getObjectManager();
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode('frontend');
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
try {
$productId = 1; // Replace with a valid product ID
$product = $productRepository->getById($productId);
echo "Product Name: " . $product->getName() . PHP_EOL;
} catch (\Exception $e) {
echo "Error: " . $e->getMessage() . PHP_EOL;
}
How it works
All plugins are checked when Magento initializes. If a function has been extended with a plugin, the plugin functions are run in the order set by the sortOrder
in the di.xml
file.
- Each plugin is associated with a specific class and method which it intercepts.
- Magento uses dependency injection to create instances of classes.
- When a class with plugins is instantiated, Magento generates a proxy class that includes the plugin logic.
- The proxy class ensures that the plugins are executed in the correct order when the target method is called.
Plugins Sort Order
If multiple plugins are listening to the same method, they follow below execution order :
- The before plugin functions with the lowest sortOrder value
- The around plugin functions with the lowest sortOrder value
- The before plugin functions following the sortOrder value from the lowest to the highest
- The around plugin functions following the sortOrder value from the lowest to the highest
- The after plugin functions with the highest sortOrder value
- The after plugin functions following the sortOrder value from the highest to the lowest
Tips for Working with Plugins
- Avoid overusing plugins: Too many plugins can affect performance. Use them judiciously.
- Debugging is key: Use var_dump or logging to verify plugin execution.
- Test your scenarios: Always validate the impact of plugins on core functionality.
- When working with the around listener, special attention is needed because it is the only listener that must return a value. If you forget to return a value, it can disrupt the execution flow, causing other around plugins for the same method to stop working.
Frequently Asked Questions
A plugin, also known as an interceptor, is a way to modify the behavior of public methods in existing classes without changing the original code.
Use plugins when you need to modify specific method behavior without rewriting the entire class. Preferences completely replace the class.
No, plugins only work with public methods.
Plugins are executed in the following order: before, around, after.
There are three types of plugins: before, after, and around.
Plugins are defined in the di.xml
file within a module.
before
plugin?A before
plugin allows you to execute custom code before the original method is called and can modify the method’s arguments.
after
plugin?An after
plugin allows you to execute custom code after the original method is called and can modify the result returned by the method.
around
plugin?An around
plugin allows you to completely control the execution of the original method, modify arguments, and the result.
The execution order is determined by the sortOrder
attribute in the di.xml
file. Lower sortOrder
values are executed first for before
and around
plugins, and last for after
plugins.
Yes, you can use multiple plugins on the same method, and they will be executed in the order specified by their sortOrder
.
$subject
parameter in a plugin method?The $subject
parameter is the instance of the original class whose method is being intercepted.
$proceed
callable in an around
plugin?The $proceed
callable is used to execute the original method within an around
plugin.
Plugins are your go-to solution for customizing Magento 2 methods without the headache of core file modifications. By mastering plugins, you ensure your Magento store is flexible, future-proof, and upgrade-safe.
Ready to create your own plugin? Start small and keep experimenting. Remember, with great power comes great debugging responsibility!
Let me know in the comments if you are having any queries.
If you love this tutorials, feel free to share with colleagues or bookmark this to visit later.
If you are interested in receiving snippets for enhancing your Magento 2 skills, don’t forget to subscribe to my newsletters for amazing tutorials at https://jigarkarangiya.com/newsletter/
Thank you
You may also like,
How to Print Collection Query in Magento 2
How to Remove a Link from the Customer Account Menu in Magento 2?
Adobe Commerce Cloud Project Structure
People also searched for
- How to override a model in Magento 2
- Dependency Injection (DI) in Magento 2 explained
- What are preferences in Magento 2?
- Magento 2: Plugins vs Observers – Which one to use?
- Best practices for Magento 2 module development
- How to debug plugins in Magento 2
- Create custom events in Magento 2
- Common mistakes when using plugins in Magento 2
Leave a Comment