Magento 2 – How to add new order attribute
In this tutorial, we are going to create a new order attribute and show it in admin grid. Let’s say we want to set “Is Important” to some orders (logic is up to you). First thing we need to do is to create a new module (you can add this functionality to existing module as well). Creating a basic module is out of scope of this tutorial.
Next we need to create a setup script for our module. Setup scripts in Magento 2 should be created in Yereone/NewOrderAttribute/Setup/InstallData.php. The content will be the following
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<?php namespace Yereone\NewOrderAttribute\Setup; use Magento\Framework\Setup\InstallDataInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Sales\Model\Order; class InstallData implements InstallDataInterface { /** * @var \Magento\Sales\Setup\SalesSetupFactory */ protected $salesSetupFactory; /** * @param \Magento\Sales\Setup\SalesSetupFactory $salesSetupFactory */ public function __construct( \Magento\Sales\Setup\SalesSetupFactory $salesSetupFactory ) { $this->salesSetupFactory = $salesSetupFactory; } /** * {@inheritDoc} */ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) { $installer = $setup; $installer->startSetup(); $salesSetup = $this->salesSetupFactory->create(['resourceName' => 'sales_setup', 'setup' => $installer]); $salesSetup->addAttribute(Order::ENTITY, 'is_important', [ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 'length'=> 255, 'visible' => false, 'nullable' => true ]); $installer->getConnection()->addColumn( $installer->getTable('sales_order_grid'), 'is_important', [ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 'length' => 255, 'comment' =>'Is Important' ] ); $installer->endSetup(); } } |
As you may know, order grid content is not populated from main sales_order table. sales_order_grid tables is used instead, which is pre populated with information from sales_order, sales_order_payment and other tables. So we created columns for our new attribute in both sales_order and sales_order_grid tables. We are going to set attribute value in Order model, which is represented in sales_order table, so we need to tell magento to copy value from sales_order to sales_order_grid table when new order is created. That is done by di.xml file. Create di.xml in Yereone/NewOrderAttribute/etc/di.xml with the following content.
1 2 3 4 5 6 7 8 9 10 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="Magento\Sales\Model\ResourceModel\Order\Grid" type="Magento\Sales\Model\ResourceModel\Grid"> <arguments> <argument name="columns" xsi:type="array"> <item name="is_important" xsi:type="string">sales_order.is_important</item> </argument> </arguments> </virtualType> </config> |
The actual grid on the frontend is rendered by sales_order_grid.xml UI component. If we did everything correctly, it will have the information about our new attribute. So the next thing is to tell him to create a column for it. Create a new xml file in
Yereone/NewOrderAttribute/view/adminhtml/ui_component/sales_order_grid.xml with the following content
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="UTF-8"?> <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> <columns name="sales_order_columns"> <column name="is_important"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Is Important</item> </item> </argument> </column> </columns> </listing> |
At this moment, you should already see the column in admin grid, but the value will be empty because we have not set it yet. Order attribute value can be set from different places. One method I will show is to set it when the order is created. That will be done on sales_order_save_before event. So create new events.xml file in Yereone/NewOrderAttribute/etc/events/xml with the following content
1 2 3 4 5 6 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="sales_order_save_before"> <observer name="set_order_attribute" instance="Yereone\NewOrderAttribute\Observer\SetOrderAttribute"/> </event> </config> |
And the actual code for this will be in Yereone\NewOrderAttribute\Observer\SetOrderAttribute.php with the following content
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php namespace Yereone\NewOrderAttribute\Observer; class SetOrderAttribute implements \Magento\Framework\Event\ObserverInterface { /** * @param \Magento\Framework\Event\Observer $observer * @return $this */ public function execute(\Magento\Framework\Event\Observer $observer) { /** @var \Magento\Sales\Model\Order $order */ $order = $observer->getEvent()->getOrder(); if ('some logic') { $order->setIsImportant("Yes"); } return $this; } } |
Now after doing a new order, you should already see the value in admin grid.
Here is the module with all files in Yereone Github Repository.
https://github.com/yereone/NewOrderAttribute
I was creating a new script for my Magento store because I had to add new order attribute, Yous post is very helpful and figured out the issue, here’s another guide which helped me to create script, https://www.cloudways.com/blog/setup-scripts-in-magento-2/. Hope, It will help your readers as well.
I have followed your tutorial and when I try to install the module runing setup:upgrade comment I get an error message
“Bachus\OrderAttribute\Setup\InstallSchema must implement \Magento\Framework\Setup\InstallSchemaInterface”
Hi. This means your setup class doesn’t implement \Magento\Framework\Setup\InstallSchemaInterface. Please check the top part of your InstallSchema file.
I know that but your script have a bug I think because it implements InstallDataInterface when I change it acrording to magento prompt it gets another error whih says that class InstallSchema need to suit the InstallSchema interface. The another bug is that I can not display label in grid and the filters disaperad. Aslo ModuleDir/view/adminhtml/uiComponent/sales_order_grid.xml is incorrect. It schould be ui_component insted uiComponent. The observer works fine and I can see the value in grid.
Hi. Thank you for your response. We updated the code, fixed the issues, and placed the code on Github.
https://github.com/yereone/NewOrderAttribute
Thanks
Hi,
How can we add the multiple order attributes
Hi. Use $eavSetup->addAttribute() function for each attribute to create the attributes in the database, and also for each attribute in the xml file to show them in backend form.