How to add extension attribute in Magento2

Discovering How to add extension attribute in Magento2

In this tutorial “How to add extension attribute in Magento2“, we delve into the process of incorporating extension attributes within Magento 2. These attributes serve the purpose of expanding the functionality of interfaces.In contrast to custom attributes, extension attributes frequently employ intricate data types. Importantly, these attributes remain concealed from the Admin interface.

The introduction of extension attributes proves invaluable in overcoming the constraints imposed by scalar values. By seamlessly integrating extension attributes, we acquire the capability to extend both EAV (Entity-Attribute-Value) and non-EAV structures with sophisticated objects. Consequently, this enhances the overall versatility of Magento 2.

External developers face limitations when attempting to modify API data interfaces within the Adobe Commerce and Magento Open Source code. Despite this constraint, a valuable feature known as extension attributes is often available for most entities. To ascertain their availability for a specific entity, one should inspect the interface for the presence of methods such as getExtensionAttributes() and setExtensionAttributes().

This demonstration aims to elucidate the process of incorporating extension attributes into a Product entity, the Product Repository, and provides an illustrative example using Web API.

When interacting with the API to retrieve either a singular product or a list of products, it is essential to query the pertinent service—specifically, the Product Repository. The ensuing responses will manifest as objects adhering to the subsequent structure:

Product Response:

<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>

Product List Response:

<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>

In these XML representations, the tags serve as designated points for adding extension attributes data. By understanding and implementing this process, developers can enhance the functionality and capabilities of Magento entities through the strategic integration of extension attributes.

Integrate Plugin into Product Repository

To incorporate extension attributes, it is necessary to implement an after plugin on the Product Repository. This plugin should be declared for the following methods: save, get, and getList.

You can add both scalar and non-scalar extension attributes. Scalar attributes represent simple attributes, while Data Objects can represent non-scalar attributes.

<?php
/**
 * Copyright &copy; Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Api\Data\ProductInterface;

public function afterGet

(
    ProductRepositoryInterface $subject,
    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;
}

This approach serves as the simplest method to add extension attributes without causing conflicts:

  1. Retrieve the entity’s extension attributes, if already set.
  2. Add the designated extension attribute.
  3. Set the extension attribute on the entity, including the newly added one.

The afterGetList function is similar to afterGet:

<?php
/**
 * Copyright &copy; Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Api\Data\ProductSearchResultsInterface;

public function afterGetList(
    ProductRepositoryInterface $subject,
    ProductSearchResultsInterface $searchResults
) : ProductSearchResultsInterface {
    $products = [];
    foreach ($searchResults->getItems() as $entity) {
        $ourCustomData = $this->customDataRepository->get($entity->getId());

        $extensionAttributes = $entity->getExtensionAttributes();
        $extensionAttributes->setOurCustomData($ourCustomData);
        $entity->setExtensionAttributes($extensionAttributes);

        $products[] = $entity;
    }
    $searchResults->setItems($products);
    return $searchResults;
}

To add extension attributes to an entity without plugins, use the extensionActions argument of \Magento\Framework\EntityManager\Operation\ExtensionPool. See \Magento\Catalog\Model\ProductRepository::getList() as an example of an implementation.

If entities lack an implementation to fetch extension attributes, utilize the afterSave plugin to manipulate the entity data before returning it.

<?php
/**
 * Copyright &copy; Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;

public function afterSave

(
    ProductRepositoryInterface $subject,
    ProductInterface $result, /** result from the save call **/
    ProductInterface $entity  /** original parameter to the call **/
    /** other parameter not required **/
) {
    $extensionAttributes = $entity->getExtensionAttributes(); /** get original extension attributes from entity **/
    $ourCustomData = $extensionAttributes->getOurCustomData();
    $this->customDataRepository->save($ourCustomData);

    $resultAttributes = $result->getExtensionAttributes(); /** get extension attributes as they exist after save **/
    $resultAttributes->setOurCustomData($ourCustomData); /** update the extension attributes with correct data **/
    $result->setExtensionAttributes($resultAttributes);

    return $result;
}

If an entity does not have an implementation for extension attributes, you need to use the afterGetExtensionAttributes plugin. Assume the product entity lacks this implementation; the corresponding plugin might appear as follows:

<?php
/**
 * Copyright &copy; Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

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;
    }
}

Lastly, associate the plugin with the 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>

By adhering to these procedures, developers can seamlessly enhance the capabilities of Magento entities through the strategic implementation of extension attributes.

Configure Extension Attributes

To define extension attributes, the corresponding file must be located within your module’s /etc folder.

For scalar attributes:

<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="int" />
        <attribute code="second_custom_attribute" type="string" />
    </extension_attributes>
</config>

Here, scalar attributes represent simple attribute types like integers or strings. Specify the class or interface of the extension attributes within the “for” attribute of the tag—ProductInterface in this case. Each attribute is identified by a unique code and its associated data type

For non-scalar attributes:

<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>

Non-scalar attributes refer to data objects, such as instances of a class. In this example, we add the CustomDataInterface object as an extension attribute.

For array extension attributes:

<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="some_custom_data" type="string[]" />
    </extension_attributes>
</config>

Array extension attributes extend scalar attributes, allowing a range of values to be represented. The [] symbol indicates the attribute type is an array. This notation can also be appended to non-scalar types.

In the first (scalar) case, the resulting XML structure is as follows:

<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>foo</second_custom_attribute>
    </extension_attributes>
</product>

This structure showcases how scalar extension attributes like ‘first_custom_attribute’ and ‘second_custom_attribute’ can be seamlessly integrated into the product data.

In the second (non-scalar) case:

<product>
    <id>1</id>
    <sku>some-sku</sku>
    <custom_attributes><!-- Custom Attributes Data --></custom_attributes>
    <extension_attributes>
        <our_custom_data>
            <!-- fields defined in CustomDataInterface are here -->
        </our_custom_data>
    </extension_attributes>
</product>

Here, the ‘our_custom_data’ attribute, being non-scalar, allows for a structured representation, accommodating fields defined in the associated CustomDataInterface.

For the third case (array) represented in JSON:

{
  "id": 1,
  "sku": "some-sku",
  "custom_attributes": { /* ... custom attribute data ... */ },
  "extension_attributes": {
    "some_custom_data": ["value1", "value2", "value3"]
  }
}

In this JSON structure, ‘some_custom_data’ is an array attribute capable of holding multiple values, providing a flexible and dynamic approach to data representation.

Understanding the distinctions between scalar, non-scalar, and array extension attributes allows developers to tailor their data structures to specific use cases, fostering a more adaptable and extensible Magento environment.


I hope you found the article on “How to add extension attribute in Magento2” helpful, and kindly consider sharing it with others. you can also check another article related to extension attribute that is “Understand what is extension attribute

How to add extension attribute in Magento2
Tagged on:                 

One thought on “How to add extension attribute in Magento2

Leave a Reply

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