Reading list Switch to dark mode

    Magento2 Interceptor pattern and code generation

    Updated 6 March 2024

    In my previous blog we have tried to understood the concept of code generation and why it is needed, and we also understood the concept of factory code generation, now in this blog we will understand about interceptor pattern and code generation.

    As we know design patterns are used to solve specific problems and interceptor design pattern also used in magento2 to solve the problem of customization. Since in a system like magento there are lots of developers working and creating extention, and they may try to customize the magento core functions for some specific requirements, so it is very important to have a better system and approach for customization in magento.

    Problem:

    In magento1 there was rewrite system for customization, where you can easily overrite the core class in your module and magento will start using your class instead of core class, but the problem occurs when there are two or more modules overriting the same core class, in this case only one module will work fine but other modules customization in the core class will not work.

    Solution:

    Searching for an experienced
    Magento 2 Company ?
    Find out More

    for the solution of the above problem magento2 now uses interceptor design patter or plugin system.

    What is Interceptor design pattern ?

    In the field of software development, an interceptor pattern is a software design pattern that is used when software systems or frameworks want to offer a way to change, or augment, their usual processing cycle

    –Source

    Magento2 Interceptor code generation:

    Now we will see how interceptor code generation works. Unlike factory you don’t use interceptor classes directly, they are used without the knowledge of the user .An interceptor class is generated when it encounters a plugin declaration in the di.xml file. Lets see how plugins are defined in di.xml:

    <type name="Magento\Customer\Model\ResourceModel\Visitor">
    
    <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" />
    
    </type>

    if the object manager encounters the above type declaration in the di.xml then it automatically generate interceptor class in the generated/code folder .

    In the type declaration :

    type attribute “name”: defines the class that need to be intercepted.

    “plugin” tag: defines plugin declaration

    plugin “name” attribute : plugin identifier

    plugin “type” attribute :  your class in which you will define the method need to be customized.

    For more details about plugins and how to use them you can go through this blog :

    create and use plugins

    or simply view this video:

    Magento2 Plugins

    Plugin class created to work after clean method of 
    Magento\Customer\Model\ResourceModel\Visitor class

    <?php
    /**
     * Plugin for \Magento\Customer\Model\ResourceModel\Visitor model
     *
     * Copyright © 2016 Magento. All rights reserved.
     * See COPYING.txt for license details.
     */
    namespace Magento\Catalog\Model\Plugin;
    
    class Log
    {
        /**
         * @var \Magento\Catalog\Model\Product\Compare\Item
         */
        protected $_productCompareItem;
    
        /**
         * @param \Magento\Catalog\Model\Product\Compare\Item $productCompareItem
         */
        public function __construct(\Magento\Catalog\Model\Product\Compare\Item $productCompareItem)
        {
            $this->_productCompareItem = $productCompareItem;
        }
    
        /**
         * Catalog Product Compare Items Clean
         * after plugin for clean method
         *
         * @param \Magento\Customer\Model\ResourceModel\Visitor $subject
         * @param \Magento\Customer\Model\ResourceModel\Visitor $logResourceModel
         *
         * @return \Magento\Customer\Model\ResourceModel\Visitor
         * @SuppressWarnings(PHPMD.UnusedFormalParameter)
         */
        public function afterClean(\Magento\Customer\Model\ResourceModel\Visitor $subject, $logResourceModel)
        {
            $this->_productCompareItem->clean();
            return $logResourceModel;
        }
    }

    in the above class a plugin is created to work after the clean method of \Magento\Customer\Model\ResourceModel\Visitor

    afterClean:  plugin method to work after clean method to modify its return data, or to do something before returning some data.
    \Magento\Customer\Model\ResourceModel\Visitor $subject
    : original class passed as argument so that you can use any of its public methods.
    $logResourceModel
    : this is the original response from the clean method so that user it can be modified and returned .

    Now we will see the structure of the interceptor class that is generated automatically in generated/code folder:

    <?php
    namespace Magento\Customer\Model\ResourceModel\Visitor;
    
    /**
     * Interceptor class for @see \Magento\Customer\Model\ResourceModel\Visitor
     */
    class Interceptor extends \Magento\Customer\Model\ResourceModel\Visitor implements \Magento\Framework\Interception\InterceptorInterface
    {
        use \Magento\Framework\Interception\Interceptor;
    
        public function __construct(\Magento\Framework\Model\ResourceModel\Db\Context $context, \Magento\Framework\Stdlib\DateTime\DateTime $date, \Magento\Framework\Stdlib\DateTime $dateTime, $connectionName = null)
        {
            $this->___init();
            parent::__construct($context, $date, $dateTime, $connectionName);
        }
    
        /**
         * {@inheritdoc}
         */
        public function clean(\Magento\Customer\Model\Visitor $object)
        {
            $pluginInfo = $this->pluginList->getNext($this->subjectType, 'clean');
            return $pluginInfo ? $this->___callPlugins('clean', func_get_args(), $pluginInfo) : parent::clean($object);
        }
    }
    

    In the above interceptor class you can see in has extended the original class so that it can override the function that plugin is needed, you can also see that it has implemented
    \Magento\Framework\Interception\InterceptorInterface 

    and inside, it uses its concrete class, this class has a method .

    Lets see some of the methods used in this interceptor class and its usage:

    ___init(): this method is called in the constructor it is simply loading all the plugin that are defined for the class in pluginList property.

    clean(\Magento\Customer\Model\Visitor $object): this method in overridden in this interceptor class, since we needed to change its behavior.

    $pluginInfo = $this->pluginList->getNext($this->subjectType, 'clean'); :

    in this line inside clean method we are loading all the plugin for the class method clean(), and you can see that “pluginList” property used which was initialized  by calling the ___init() method inside the constructor, $pluginInfo will have the information about the plugin like when plugin need to be called around, after or before.

    then it check if there is any plugin configured or not, if not it calls the original parent method

    parent::clean($object);

    otherwise your parent method will be called.

    $this->___callPlugins: this will call the plugin method according to around, after or before listeners.

    Why interceptors need to be generated automatically :

    As we can see there is uncertainty that which class interceptor is needed, there can be any class which need to be customized according to the requirement, so it is best to generate the class automatically when a plugin is found in the di.xml file.

    That’s all for now, I’ll discuss proxy design pattern in my next article, till then if you have any doubt in this blog you can ask me in the comments below.

    Thanks 🙂

    . . .

    Leave a Comment

    Your email address will not be published. Required fields are marked*


    2 comments

  • Rama
    • ashutosh srivastava (Moderator)
  • Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home