Magento 2: Before & After Method Observer using Plugin

Magento 2 provides a new feature called Plugin or Interceptor that is used to run some code before/after/around any function call of any public class. Hence, with the help of Plugins, we can change the behavior of class method without making any changes in the code of the class itself. This also avoids conflicts with other modules.

Let’s suppose your module is named YourCompany_YourModule.

The plugin class has to be declared in etc/di.xml of your module. Here is the code:

app/code/YourCompany/YourModule/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="Magento\Checkout\Model\Cart">
        <plugin name="pluginAddProductToCart" type="YourCompany\YourModule\Plugin\CartPlugin" sortOrder="10" disabled="false"/>
    </type>
</config>

Here,

type’s name = class whose methods are to be observed
plugin’s name = random plugin name
plugin’s type = name of plugin’s class (YourCompany\YourModule\Plugin\Plugin)
plugin’s sortOrder = the order of the plugin to be called
plugin’s disabled = enable/disable plugin, default value is false.

We can add before, after, and around methods to modify the core class functions. For example, if there is a “Save” function in the core class then in the plugin class we can have beforeSave, afterSave and aroundSave method.

beforeMethod = contains code to run before the observed Method
afterMethod = contains code to run after the observed Method
aroundMethod = contains code to run both before and after the observed Method

“observed method” means the function present in the Core class which we want to modify through our Plugin class

In the above di.xml file, we have defined that we are going to observe methods of class Magento\Checkout\Model\Cart in our plugin class YourCompany\YourModule\Plugin\CartPlugin.

In this example, we will be observing a function named addProduct of the core Cart class.

For this example,

If you want to run some code before the addProduct method (adding product to cart), then you will have to create a method named beforeAddProduct in your Plugin class.

Similarly, if you want to do something after adding product to cart, then you will have to create a new function named afterAddProduct in your Plugin class.

And, there is another method named ‘around’. This allows you to execute some code both before and after the observed method is called. For this, you will have to add a new function named aroundAddProduct in your Plugin class.

Here is the CartPlugin class.

app/code/YourCompany/YourModule/Plugin/CartPlugin.php


<?php

namespace YourCompany\YourModule\Plugin;

use Magento\Framework\Exception\LocalizedException;

class CartPlugin
{
    /**
     * @var \Magento\Quote\Model\Quote
     */
    protected $quote;
    
    protected $request;

    /**
     * Plugin constructor.
     *
     * @param \Magento\Checkout\Model\Session $checkoutSession
     */
    public function __construct(
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Framework\App\Request\Http $request        
    ) {
        $this->quote = $checkoutSession->getQuote();
        $this->request = $request;        
    }

    /**
     * beforeAddProduct
     *
     * @param      $subject
     * @param      $productInfo
     * @param null $requestInfo
     *
     * @return array
     * @throws LocalizedException
     */
    public function beforeAddProduct($subject, $productInfo, $requestInfo = null)
    {       
        $productId = (int)$this->request->getParam('product', 0);       
        $qty = (int)$this->request->getParam('qty', 1);             
        
        // do something
        // your code goes here
        
        if ( something wrong ) {
            throw new LocalizedException(__('Your error message'));
        }
        
        return [$productInfo, $requestInfo];
    }
    
    /**
     * afterAddProduct
     *
     * @param      $subject
     * @param      $result  Returned value from core observed method 'addProduct'     
     */
    public function afterAddProduct($subject, $result)
    {
        $quote = $result->getQuote();
        
        // do something
        // your code goes here      
    }
    
    public function aroundAddProduct($subject, $proceed)
    {
        // do something 
        // before adding product to cart
        // your code goes here
        $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) {
            // do something
            // after adding product to cart
            // your code goes here
            
        }
        
        return $returnValue;    
    }
}
?>

Read more about Magento 2 plugins in the official doc: Magento 2 Plugins

Hope this helps. Thanks.