Magento2 programmatically add custom data to checkout and show on order.
Step 1. Register your module Vendor_Module:
etc/module.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Vendor_Module" setup_version="1.3.1"> </module> </config>
registration.php
<?php // @codeCoverageIgnoreStart \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Vendor_Module', __DIR__ ); // @codeCoverageIgnoreEnd
Step 2 Create a installData.php or upgradeData.php and addAttribute to quote and order. I use custom data name “contact_type”.
<?php /** * Created by PhpStorm. * User: thelightsp * Date: 6/30/19 * Time: 7:45 AM */ namespace Vendor\Module\Setup; use Magento\Eav\Setup\EavSetupFactory; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Setup\UpgradeDataInterface; use Magento\Quote\Setup\QuoteSetupFactory; use Magento\Sales\Setup\SalesSetup; use Magento\Sales\Setup\SalesSetupFactory; use Magento\Framework\DB\Ddl\Table; class UpgradeData implements UpgradeDataInterface { /** * @var EavSetupFactory */ public $eavSetupFactory; /** * @var \Magento\Framework\ObjectManagerInterface */ public $objectManager; /** * @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ public $eavAttribute; /** * @var \Magento\Framework\App\State */ protected $state; /** * @var QuoteSetupFactory */ protected $quoteSetupFactory; /** * @var SalesSetupFactory */ protected $salesSetupFactory; /** * UpgradeData constructor. * @param EavSetupFactory $eavSetupFactory * @param \Magento\Framework\ObjectManagerInterface $objectManager * @param \Magento\Framework\App\State $state * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $eavAttribute * @param QuoteSetupFactory $quoteSetupFactory * @param SalesSetupFactory $salesSetupFactory */ public function __construct( EavSetupFactory $eavSetupFactory, \Magento\Framework\ObjectManagerInterface $objectManager, \Magento\Framework\App\State $state, \Magento\Catalog\Model\ResourceModel\Eav\Attribute $eavAttribute, QuoteSetupFactory $quoteSetupFactory, SalesSetupFactory $salesSetupFactory ) { $this->eavSetupFactory = $eavSetupFactory; $this->objectManager = $objectManager; $this->eavAttribute = $eavAttribute; $this->state = $state; $this->quoteSetupFactory = $quoteSetupFactory; $this->salesSetupFactory = $salesSetupFactory; } /** * @param ModuleDataSetupInterface $setup * @param ModuleContextInterface $context */ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) { $setup->startSetup(); if (version_compare($context->getVersion(), '1.3.1', '<')) { /** @var QuoteSetup $quoteSetup */ $quoteSetup = $this->quoteSetupFactory->create(['setup' => $setup]); $quoteSetup ->addAttribute( 'quote', 'contact_type', ['type' => Table::TYPE_TEXT, 'required' => false] ); /** @var SalesSetup $salesSetup */ $salesSetup = $this->salesSetupFactory->create(['setup' => $setup]); $salesSetup ->addAttribute( 'order', 'contact_type', ['type' => Table::TYPE_TEXT, 'required' => false] ); } } }
Step 3: Add custom data component on layout: view/frontend/layout/checkout_index_index.xml
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="checkout" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="checkout.root"> <arguments> <argument name="jsLayout" xsi:type="array"> <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> <item name="children" xsi:type="array"> <item name="sidebar" xsi:type="array"> <item name="children" xsi:type="array"> <item name="summary" xsi:type="array"> <item name="children" xsi:type="array"> <item name="itemsAfter" xsi:type="array"> <item name="children" xsi:type="array"> <item name="contact-type" xsi:type="array"> <item name="component" xsi:type="string">Vendor_Module/js/view/sidebar/contact-type</item> <item name="sortOrder" xsi:type="string">12</item> <item name="displayArea" xsi:type="string">contact-type</item> <item name="dataScope" xsi:type="string">contactType</item> <item name="provider" xsi:type="string">checkoutProvider</item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </body> </page>
Step 4: Add component of your field: view/frontend/web/js/view/sidebar/contact-type.js
define( [ 'ko', 'uiComponent' ], function (ko, Component ) { 'use strict'; return Component.extend({ defaults: { template: 'Vendor_Module/sidebar/contact-type', inputValue: '' }, isVisible: true, /** * @inheritdoc */ initObservable: function () { this._super().observe({ CheckVal1: ko.observable(false) }); var contactType= []; this.CheckVal1.subscribe(function (newValue) { window.checkoutConfig.contact_type = newValue; }); return this; } }); } );
Step 5: add component template: view/frontend/web/template/sidebar/contact-type.html
<div class="aw-sidebar_contact-type" data-bind="visible: isVisible"> <span data-role="title" class="toggle" data-bind="i18n:'Contacts'"></span> <div class="content" data-role="content"> <div class="contact"> <div> <div class="control"> <input type="checkbox" data-bind='checked: CheckVal1' id="contact[phone]" name="contact_phone" value="1" class="checkbox"> <label></label> </div> <label for="contact[phone]">Your checkbox</label> </div> </div> </div> </div>
Step 6: Add your attribute value to payment extension attribute:view/frontend/web/js/model/place-order-mixin.js
define([ 'jquery', 'mage/utils/wrapper', 'Magento_Checkout/js/model/full-screen-loader' ], function ( $, wrapper, fullScreenLoader ) { 'use strict'; return function (placeOrderAction) { return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) { paymentData['extension_attributes']['contact_type'] = window.checkoutConfig.contact_type; return originalAction(paymentData, messageContainer).fail( function () { fullScreenLoader.stopLoader(); } ); }); }; });
Step 7: add your extension_attributes in Vendor_Modules/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\Quote\Api\Data\PaymentInterface"> <attribute code="contact_type" type="string" /> </extension_attributes> <extension_attributes for="Magento\Quote\Api\Data\CartInterface"> <attribute code="contact_type" type="string" /> </extension_attributes> <extension_attributes for="Magento\Sales\Api\Data\OrderInterface"> <attribute code="contact_type" type="string" /> </extension_attributes> </config>
Step 8: Add plugin to modify data payment from extension attribute and order interface:
<?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\Checkout\Api\PaymentInformationManagementInterface"> <plugin name="contactType" type="Vendor\Module\Model\Plugin\ContactType"/> </type> <type name="Magento\Sales\Api\OrderRepositoryInterface"> <plugin name="contacttype-order-repository-plugin" type="Vendor\Module\Plugin\Order\OrderRepositoryPlugin"/> </type> </config>
<?php namespace Vendor\Module\Model\Plugin; use Magento\Checkout\Api\PaymentInformationManagementInterface; use Magento\Quote\Api\Data\PaymentInterface; class ContactType { /** * @param PaymentInformationManagementInterface $subject * @param int $cartId * @param PaymentInterface $paymentMethod * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function beforeSavePaymentInformationAndPlaceOrder( PaymentInformationManagementInterface $subject, $cartId, PaymentInterface $paymentMethod ) { if($paymentData->getExtensionAttributes()->getContactType()){ $quote = $this->quoteRepository->getActive($cartId); $quote->setContactType($paymentData->getExtensionAttributes()->getContactType()); $this->quoteRepository->save($quote); } } /** * @param PaymentInformationManagementInterface $subject * @param int $cartId * @param PaymentInterface $paymentMethod * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function beforeSavePaymentInformation( PaymentInformationManagementInterface $subject, $cartId, PaymentInterface $paymentMethod ) { if($paymentData->getExtensionAttributes()->getContactType()){ $quote = $this->quoteRepository->getActive($cartId); $quote->setContactType($paymentData->getExtensionAttributes()->getContactType()); $this->quoteRepository->save($quote); } } }
Step 9: add data to event quote submit before: Vendor_Module/etc/events.xml
<?xml version="1.0" encoding="UTF-8"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="sales_model_service_quote_submit_before"> <observer name="aw_osc_quote_submit_before" instance="Vendor\Module\Observer\QuoteSubmitBeforeObserver" /> </event> </config>
<?php namespace Vendor\Module\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Quote\Model\Quote; use Magento\Sales\Api\Data\OrderInterface; class QuoteSubmitBeforeObserver implements ObserverInterface { /** * {@inheritdoc} */ public function execute(Observer $observer) { $event = $observer->getEvent(); /** @var OrderInterface $order */ $order = $event->getOrder(); /** @var Quote $quote */ $quote = $event->getQuote(); $order->setContactType($quote->getContactType()); return $this; } }
Step 10: Set your custom data to order:
<?php namespace Vendor\Module\Plugin\Order; use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\Data\OrderExtensionFactory; use Magento\Sales\Api\Data\OrderExtensionInterface; class OrderRepositoryPlugin { /** * @var OrderExtensionFactory */ private $orderExtensionFactory; /** * @param OrderExtensionFactory $orderExtensionFactory */ public function __construct( OrderExtensionFactory $orderExtensionFactory ) { $this->orderExtensionFactory = $orderExtensionFactory; } /** * Add extension attributes to order * * @param OrderRepositoryInterface $subject * @param OrderInterface $order * @return OrderInterface */ public function afterGet(OrderRepositoryInterface $subject, OrderInterface $order) { $this->setExtensionAttributes($order); return $order; } /** * Set extension attributes to order entity * * @param OrderInterface $order */ private function setExtensionAttributes(OrderInterface $order) { /** @var OrderExtensionInterface $extensionAttributes */ $extensionAttributes = $order->getExtensionAttributes(); if ($extensionAttributes === null) { $extensionAttributes = $this->orderExtensionFactory->create(); } $extensionAttributes->setContactType($order->getContactType()); $order->setExtensionAttributes($extensionAttributes); } }
That is all step add your custom data to checkout and order via checkout and database.
Step 11: Show custom data to order view.
Create layout referer and show your block: Vendor/Module/view/adminhtml/layout/sales_order_view.xml
Create your block: Vendor/Module/Block/Adminhtml/Order/View/ContactType.php
Create your template: Vendor/Module/view/adminhtml/templates/order/view/contacttype.phtml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="order_additional_info"> <block class="Vendor\Module\Block\Adminhtml\Order\View\ContactType" name="order.view.contacttype" template="Vendor_Module::order/view/contacttype.phtml"/> </referenceBlock> </body> </page>
<?php /** * Created by PhpStorm. * User: thelightsp * Date: 6/30/19 * Time: 4:00 PM */ namespace Vendor\Module\Block\Adminhtml\Order\View; class ContactType extends \Magento\Sales\Block\Adminhtml\Order\AbstractOrder { /** * ContactType constructor. * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Sales\Helper\Admin $adminHelper * @param array $data */ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Framework\Registry $registry, \Magento\Sales\Helper\Admin $adminHelper, array $data = []) { parent::__construct($context, $registry, $adminHelper, $data); } /** * @return string * @throws \Magento\Framework\Exception\LocalizedException */ public function getContactType(){ return $this->getOrder()->getContactType(); } }
<div class="admin__page-section-item" style="display: block;width: 100%"> <div class="admin__page-section-item-title"> <span class="title"><?= $block->escapeHtml(__('Customer Communication')) ?></span> </div> <address class="admin__page-section-item-content"> <?= /* @noEscape */ $block->getContactType(); ?> </address> </div>
That is all step create custom data add to checkout and show on your order. Hope it will help you well.