Hyvä Theme is Now Open Source: What This Means for Magento Community - Mageplaza
Hyvä is now Open Source and free. Discover what changed, what remains commercial, how it impacts the Magento ecosystem, and how to maximize its full potential.
Vinh Jacker | 03-17-2025
Proxies is a powerful and easy technique to help you overcome a huge problem of Magento 2. However, its role and importance are still underestimated. Therefore, in this post, I am going to help you to understand what is Magento 2 proxies and its need in Magento 2.
Main contents
Just similar to design patterns which are created to solve a redundant problem in the project, proxy design pattern solves a particular problem. Proxies work as a surrogate which means it acts on behalf of others, in programming, they are classes which could be used instead of any other class. More specifically, in Magento 2, proxies are used to replace resource hungry classes.
However, when replacing like that, an issue happens in Magento 2. The following section will tell you the problems caused in Magento 2 particularly.
In Magento 2, using constructor injection faces challenges when attempting to instantiate another class within your own. Instead of directly creating an instance, injecting the object through the constructor is recommended, allowing it to be used in the class. However, when you instantiate your class, all injected dependencies in the constructor are triggered, causing a slowdown in the process.
To solve this issue, the proxy design pattern is applied. By using Magento 2 proxies, you can delay the instantiation of certain dependencies until they are actually needed, optimizing the performance of your Magento 2 application.
In Magento 2, dependency injection was introduced by a new concept. Although there are various types of dependency, constructor injection and method injection are the best, and both of them are used by Magento 2. However, there is a problem with constructor injection.
In details, if you want any other class object to be used in your class, instead of instantiating it inside the class, you should inject that object to the constructor and then use it in the class. If you do that, when your class is instantiated, all the dependencies which are injected in your class constructor will also be instantiated. As a result, a chain reaction of object creation will be triggered, which can lead to the process being slow down. Therefore, to prevent the object creation’s chain reaction, the proxy design pattern is used. For more information on managing dependencies in Magento 2, you can refer to the official Magento 2 Dependency Injection documentation.
Dependency injection has influence on the solution for the issue which is mentioned above in some way. This is because the dependency injection configuration file (di.xml) gives you the power to change the object lifestyle also known as constructor params. As a developer, you can understand which class is the culprit easily, and stop its instantiation in the constructor. In order to do that, add a type configuration in the di.xml, please view the below code:
<type name="Magento\Catalog\Model\Product">
<arguments>
<argument name="catalogProductStatus" xsi:type="object">Magento\Catalog\Model\Product\Attribute\Source\Status\Proxy</argument>
<argument name="productLink" xsi:type="object">Magento\Catalog\Model\Product\Link\Proxy</argument>
</arguments>
</type>
The above entry is from the catalog module di.xml. You can see in this type declaration for Magento\Catalog\Model\Product class, the constructor argumets catalogProductStatus and productLink are replaced with Magento\Catalog\Model\Product\Attribute\Source\Status\Proxy and Magento\Catalog\Model\Product\Link\Proxy. These classes both have the name Proxy, you cannot find these proxy classes in the Magento code base if you check your Magento after installing it. They are created automatically by the Magento 2 code generator.
These classes will be generated under two circumstances:
php bin/magento setup:di:compile
When you execute the command above, all the di.xml files of all the modules installed in Magento 2 will be checked, and if it encounters a Proxy class and it does not exist, it will be generated automatically with the same namespace which is inside var/generation folder in the Magento 2 root.
var/generation folder and its object will be returned.So from the information above, you can see that these classes are generated on the fly with some fixed convention, which is used to replace the original object. However, how this proxy class is going to help solve the issue is still a question. To answer that question, let’s have a look at the following proxy class:
<?php
namespace Magento\Catalog\Model\Product\Attribute\Source\Status;
/**
* Proxy class for @see \Magento\Catalog\Model\Product\Attribute\Source\Status
*/
class Proxy extends \Magento\Catalog\Model\Product\Attribute\Source\Status implements \Magento\Framework\ObjectManager\NoninterceptableInterface
{
/**
* Object Manager instance
*
* @var \Magento\Framework\ObjectManagerInterface
*/
protected $_objectManager = null;
/**
* Proxied instance name
*
* @var string
*/
protected $_instanceName = null;
/**
* Proxied instance
*
* @var \Magento\Catalog\Model\Product\Attribute\Source\Status
*/
protected $_subject = null;
/**
* Instance shareability flag
*
* @var bool
*/
protected $_isShared = null;
/**
* Proxy constructor
*
* @param \Magento\Framework\ObjectManagerInterface $objectManager
* @param string $instanceName
* @param bool $shared
*/
public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager, $instanceName = '\\Magento\\Catalog\\Model\\Product\\Attribute\\Source\\Status', $shared = true)
{
$this->_objectManager = $objectManager;
$this->_instanceName = $instanceName;
$this->_isShared = $shared;
}
/**
* @return array
*/
public function __sleep()
{
return ['_subject', '_isShared', '_instanceName'];
}
/**
* Retrieve ObjectManager from global scope
*/
public function __wakeup()
{
$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
}
/**
* Clone proxied instance
*/
public function __clone()
{
$this->_subject = clone $this->_getSubject();
}
/**
* Get proxied instance
*
* @return \Magento\Catalog\Model\Product\Attribute\Source\Status
*/
protected function _getSubject()
{
if (!$this->_subject) {
$this->_subject = true === $this->_isShared
? $this->_objectManager->get($this->_instanceName)
: $this->_objectManager->create($this->_instanceName);
}
return $this->_subject;
}
/**
* {@inheritdoc}
*/
public function getVisibleStatusIds()
{
return $this->_getSubject()->getVisibleStatusIds();
}
/**
* {@inheritdoc}
*/
public function getSaleableStatusIds()
{
return $this->_getSubject()->getSaleableStatusIds();
}
/**
* {@inheritdoc}
*/
public function getAllOptions()
{
return $this->_getSubject()->getAllOptions();
}
/**
* {@inheritdoc}
*/
public function getOptionText($optionId)
{
return $this->_getSubject()->getOptionText($optionId);
}
/**
* {@inheritdoc}
*/
public function addValueSortToCollection($collection, $dir = 'asc')
{
return $this->_getSubject()->addValueSortToCollection($collection, $dir);
}
/**
* {@inheritdoc}
*/
public function setAttribute($attribute)
{
return $this->_getSubject()->setAttribute($attribute);
}
/**
* {@inheritdoc}
*/
public function getAttribute()
{
return $this->_getSubject()->getAttribute();
}
/**
* {@inheritdoc}
*/
public function getOptionId($value)
{
return $this->_getSubject()->getOptionId($value);
}
/**
* {@inheritdoc}
*/
public function getFlatColumns()
{
return $this->_getSubject()->getFlatColumns();
}
/**
* {@inheritdoc}
*/
public function getFlatIndexes()
{
return $this->_getSubject()->getFlatIndexes();
}
/**
* {@inheritdoc}
*/
public function getFlatUpdateSelect($store)
{
return $this->_getSubject()->getFlatUpdateSelect($store);
}
/**
* {@inheritdoc}
*/
public function getIndexOptionText($value)
{
return $this->_getSubject()->getIndexOptionText($value);
}
/**
* {@inheritdoc}
*/
public function toOptionArray()
{
return $this->_getSubject()->toOptionArray();
}
}
Now we’re going to analyze this class to understand it:
Magento\Catalog\Model\Product\Attribute\Source\Status. This would allow you easily replace it with the original object.\Magento\Catalog\Model\Product\Attribute\Source\Status, which would allow the proxy class to use its public methods.\Magento\Framework\ObjectManager\NoninterceptableInterface interface. This is a marker interface which has no methods, no member variables. It is only used to signal that this class cannot be intercepted.__sleep, __wakeup and __sleep executes._getSubject method allows you to return the original class object when it is asked. As a result, an object will only be provided if it is requested._getSubject is being called.To sum up, using proxy classes can offer you various benefits:
di.xml file, your problem will be solved.If you have any questions or new ideas about Magento 2 Proxies, feel free to leave a comment below.