Adding extension attribute to order in Magento 2 can enhance your store’s functionality and provide more flexibility for customization.
In this guide, we’ll walk you through the steps to add an extension attribute, making it easy for you to implement this feature in your store.
Whether you’re a developer or a store owner looking to add more specific data to your orders, this tutorial will help you get the job done quickly and efficiently.
Step 1: Let’s create the extension_attributes.xml file
First and foremost, you need to declare your extension attributes in one XML file:
<!-- etc/extension_attributes.xml -->
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Sales\Api\Data\OrderInterface">
<attribute code="tigren_attribute" type="Tigren\Example\Api\Data\TigrenAttributeInterface" />
</extension_attributes>
</config>
This way, you are extending your Sales Order Interface with an attribute. It can be accessible via $order->getExtensionAttributes()->getFoomanAttribute().
Step 2: Create an interface for your extension attribute
<?php
namespace Tigren\Example\Api\Data;
interface TigrenAttributeInterface
{
const VALUE = 'value';
/**
* Return value.
*
* @return string|null
*/
public function getValue();
/**
* Set value.
*
* @param string|null $value
* @return $this
*/
public function setValue($value);
}
Step 3: Create a concrete class for the interface that you created
<?php
namespace Tigren\Example\Model;
class TigrenAttribute implements \Tigren\Example\Api\Data\FoomanAttributeInterface
{
/**
* {@inheritdoc}
*/
public function getValue()
{
return $this->getData(self::VALUE);
}
/**
* {@inheritdoc}
*/
public function setValue($value)
{
return $this->setData(self::VALUE, $value);
}
}
The interface \Magento\Sales\Api\Data\OrderExtensionInterface is generated by Magento, either in the development mode or the compilation process.
The code generation happens via \Magento\Framework\Code\Generator for any interface that cannot be loaded. It will read our XML configuration and create an interface that includes a getter and setter for tigren_attribute.
Step 4: Create a plugin to save and retrieve the new attributes
The Magento 2 plugin is built here with the purpose of adding extra behavior to the current code by executing certain code. Moreover, the plugin will enable you to execute code before, after or around any public method.
<!-- 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\Sales\Api\OrderRepositoryInterface">
<plugin name="save_tigren_attribute" type="Tigren\Example\Plugin\OrderSave"/>
<plugin name="get_tigren_attribute" type="Tigren\Example\Plugin\OrderGet"/>
</type>
</config>
As you can see, we have attached the OrderSave and OrderGet plugins to the core OrderRepositoryInterface. Now, it’s necessary to implement a specific logic for those classes.
Step 5: Save the order
You must find out a way to save your new attribute somewhere in the database.
<?php
namespace Tigren\Example\Plugin;
use Magento\Framework\Exception\CouldNotSaveException;
class OrderSave
{
...
public function afterSave(
\Magento\Sales\Api\OrderRepositoryInterface $subject,
\Magento\Sales\Api\Data\OrderInterface $resultOrder
) {
$resultOrder = $this->saveTigrenAttribute($resultOrder);
return $resultOrder;
}
private function saveTigrenAttribute(\Magento\Sales\Api\Data\OrderInterface $order)
{
$extensionAttributes = $order->getExtensionAttributes();
if (
null !== $extensionAttributes &&
null !== $extensionAttributes->getTigrenAttribute()
) {
$tigrenAttributeValue = $extensionAttributes->getTigrenAttribute()->getValue();
try {
// The actual implementation of the repository is omitted
// but it is where you would save to the database (or any other persistent storage)
$this->tigrenExampleRepository->save($order->getEntityId(), $tigrenAttributeValue);
} catch (\Exception $e) {
throw new CouldNotSaveException(
__('Could not add attribute to order: "%1"', $e->getMessage()),
$e
);
}
}
return $order;
}
}
Step 6: Order Get
<?php
namespace Tigren\Example\Plugin;
class OrderGet
{
...
public function afterGet(
\Magento\Sales\Api\OrderRepositoryInterface $subject,
\Magento\Sales\Api\Data\OrderInterface $resultOrder
) {
$resultOrder = $this->getTigrenAttribute($resultOrder);
return $resultOrder;
}
private function getTigrenAttribute(\Magento\Sales\Api\Data\OrderInterface $order)
{
try {
// The actual implementation of the repository is omitted
// but it is where you would load your value from the database (or any other persistent storage)
$tigrenAttributeValue = $this->tigrenExampleRepository->get($order->getEntityId());
} catch (NoSuchEntityException $e) {
return $order;
}
$extensionAttributes = $order->getExtensionAttributes();
$orderExtension = $extensionAttributes ? $extensionAttributes : $this->orderExtensionFactory->create();
$tigrenAttribute = $this->tigrenAttributeFactory->create();
$tigrenAttribute->setValue($tigrenAttributeValue);
$orderExtension->setTigrenAttribute($tigrenAttribute);
$order->setExtensionAttributes($orderExtension);
return $order;
}
}
IMPORTANCE: It’s worth noting that in order for the Extension Attribute to work as expected, it’s fundamental to query the entity for existing extension_attributes via $order->getExtensionAttributes() before utilizing the extension attribute factory to create a new one. In case you bypass this test, you might eliminate any previously set extension attributes on the entity.
Wrapping Up
By following these steps, you can easily add an extension attribute to an order in Magento 2.
This added flexibility allows you to customize your store to better meet your needs and those of your customers. Whether you’re adding unique identifiers, additional customer data, or other important information, extension attributes can significantly enhance your order management.
Don’t hesitate to experiment and see how these customizations can improve your store’s functionality.
Could you please give an example of the repository aswell?
Hi, thanks for the question. You’d typically need to create a repository interface that defines methods for saving, getting, and deleting your attribute data. Implementing this repository would require you to extend Magento’s native OrderRepository, adding logic to handle your custom attributes.