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
Magento 2 Default might not be functional enough for your business demand, so you need to expand Magento 2 functionalities by using third-party modules.
Extension attributes are usually used to extend default functionalities to the fullest potential. Extension attributes allow adding additional complex data to an existing entity class.
It is impossible for third-party developers to change the API Data interfaces that are defined in the Magento Core code. Nevertheless, most of these entities come with a feature called extension attributes.
In this article, I will show you how to add extension attributes to the entity in Magento 2.
Extension attributes in Magento 2 are custom attributes used to extend the functionality of core entities in both Adobe Commerce and Magento Open Source. These entities include:
Instead of modifying the core code directly, extension attributes are added through code and configuration. They allow developers to introduce additional properties or functionalities to these entities.
This feature is especially useful for customization and third-party integrations. By using extension attributes, developers can extend functionality in a flexible and scalable way without interfering with the core system. To expose these extension attributes through an API, learn how to create an API in Magento 2 and integrate it with your custom module for seamless access.
Let’s see how it is done in 3 steps:
Note:
Check the interface for the methods getExtensionAttributes() and setExtensionAttributes() to determine if they are available for the entity.
To recall a product or a list of products from the Magento API, you need to make an API request to the suitable service (the Product Repository in this case). The response to these requests will return objects with the following structure:
<product>
<id>1</id>
<sku>some-sku</sku>
<custom_attributes><!-- Custom Attributes Data --></custom_attributes>
<extension_attributes><!-- Here should we add extension attributes data --></extension_attributes>
</product>
<products>
<item>
<id>1</id>
<sku>some-sku</sku>
<custom_attributes><!-- Custom Attributes Data --></custom_attributes>
<extension_attributes><!-- Here should we add extension attributes data --></extension_attributes>
</item>
<item>
<id>2</id>
<sku>some-sku-2</sku>
<custom_attributes><!-- Custom Attributes Data --></custom_attributes>
<extension_attributes><!-- Here should we add extension attributes data --></extension_attributes>
</item>
</products>
Using an after plugin on Product Reposibility is necessary to add extension attributes. The plugin need to follow the methods including save, get, getList. We can add scalar which is a simple attribute, and non-scalar which can be shown by Data Object.
public function afterGet
(
\Magento\Catalog\Api\ProductRepositoryInterface $subject,
\Magento\Catalog\Api\Data\ProductInterface $entity
) {
$ourCustomData = $this->customDataRepository->get($entity->getId());
$extensionAttributes = $entity->getExtensionAttributes(); /** get current extension attributes from entity **/
$extensionAttributes->setOurCustomData($ourCustomData);
$entity->setExtensionAttributes($extensionAttributes);
return $entity;
}
Here is the simplest way to add extensions without causing a conflict:
You can do similar to afterGetList.
The afterSave plugin should manipulate the entity data before returning it:
public function afterSave
(
\Magento\Catalog\Api\ProductRepositoryInterface $subject,
\Magento\Catalog\Api\Data\ProductInterface $entity
) {
$extensionAttributes = $entity->getExtensionAttributes(); /** get current extension attributes from entity **/
$ourCustomData = $extensionAttributes->getOurCustomData();
$this->customDataRepository->save($ourCustomData);
return $entity;
}
However, in case some entities don’t have the implementation to fetch extension attributes, you will always retrieve null. Each time when you fetch extension attributes, you need to determine whether they are null or not. If they are null, we need to create them. To prevent such code duplication, we need to create an afterGet plugin with extension attributes for our entity.
Let’s assume that the product entity doesn’t have any implementation of extension attributes, so you can view our plugin as follows:
use Magento\Catalog\Api\Data\ProductExtensionInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductExtensionFactory;
class ProductAttributesLoad
{
/**
* @var ProductExtensionFactory
*/
private $extensionFactory;
/**
* @param ProductExtensionFactory $extensionFactory
*/
public function __construct(ProductExtensionFactory $extensionFactory)
{
$this->extensionFactory = $extensionFactory;
}
/**
* Loads product entity extension attributes
*
* @param ProductInterface $entity
* @param ProductExtensionInterface|null $extension
* @return ProductExtensionInterface
*/
public function afterGetExtensionAttributes(
ProductInterface $entity,
ProductExtensionInterface $extension = null
) {
if ($extension === null) {
$extension = $this->extensionFactory->create();
}
return $extension;
}
}
Now we need attach our plugin to ProductInterface:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Catalog\Api\Data\ProductInterface">
<plugin name="ProductExtensionAttributeOperations" type="Magento\Catalog\Plugin\ProductAttributesLoad"/>
</type>
</config>
You should use the below configuration:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Catalog\Api\Data\ProductInterface">
<attribute code="first_custom_attribute" type="Magento\SomeModule\Api\Data\CustomDataInterface" />
<attribute code="second_custom_attribute" type="Magento\SomeModule\Api\Data\CustomDataInterface" />
</extension_attributes>
</config>
Then, you will get the following result:
<product>
<id>1</id>
<sku>some-sku</sku>
<custom_attributes><!-- Custom Attributes Data --></custom_attributes>
<extension_attributes>
<first_custom_attribute>1</first_custom_attribute>
<second_custom_attribute>2</second_custom_attribute>
</extension_attributes>
</product>
You should use below configuration:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Catalog\Api\Data\ProductInterface">
<attribute code="our_custom_data" type="Magento\SomeModule\Api\Data\CustomDataInterface[]" />
</extension_attributes>
</config>
Then, you will get the following result:
<product>
<id>1</id>
<sku>some-sku</sku>
<custom_attributes><!-- Custom Attributes Data --></custom_attributes>
<extension_attributes>
<our_custom_data>
<first_custom_attribute>1</first_custom_attribute>
<second_custom_attribute>2</second_custom_attribute>
</our_custom_data>
</extension_attributes>
</product>
Above are the detailed instructions for adding extension attributes to an entity in Magento 2. I hope that this article is useful for you. If you have any questions or want to discuss anything, feel free to leave a comment below, and I will give it back to you!