I’ve created a module to add an extra field to the checkout shipping address. I can see the extra field on the checkout but the data doesn’t seem to be saving in the database using a plugin on beforeAssign
method followed by an event observer for sales_model_service_quote_submit_success
.
Example/CheckoutFields/etc/db_schema.xml
<?xml version="1.0" ?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="quote_address" resource="checkout" comment="Sales Flat Quote Address">
<column xsi:type="varchar" name="extra_field" nullable="true" length="255" comment="Extra Field"/>
</table>
<table name="sales_order_address" resource="sales" engine="innodb" comment="Sales Flat Order Address">
<column xsi:type="varchar" name="extra_field" nullable="true" length="255" comment="Extra Field"/>
</table>
</schema>
Example/CheckoutFields/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="MagentoCheckoutModelShippingInformationManagement">
<plugin name="save_extra_field" type="ExampleCheckoutFieldsModelPluginSaveAddressInformation"
sortOrder="100"/>
</type>
</config>
Example/CheckoutFields/etc/events.xml
<?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_model_service_quote_submit_success">
<observer name="custom_address_attribute_save"
instance="ExampleCheckoutFieldsObserverSaveAddressAttribute"/>
</event>
</config>
Example/CheckoutFields/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="MagentoQuoteApiDataAddressInterface">
<attribute code="extra_field" type="string"/>
</extension_attributes>
</config>
Example/CheckoutFields/Plugin/ShippingAddressManagementAssign.php
<?php
namespace ExampleCheckoutFieldsPlugin;
use MagentoQuoteModelShippingAddressManagement;
use MagentoQuoteApiDataAddressInterface;
use PsrLogLoggerInterface as Logger;
class ShippingAddressManagementAssign
{
/**
* @var Logger
*/
protected Logger $logger;
/**
* @param Logger $logger
*/
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
/**
* @param ShippingAddressManagement $subject
* @param $cartId
* @param AddressInterface $address
* @return void
*/
public function beforeAssign(
ShippingAddressManagement $subject,
$cartId,
AddressInterface $address
)
{
$extAttributes = $address->getExtensionAttributes();
if (!$extAttributes) {
return;
}
$extraField = $extAttributes->getExtraField();
if ($extraField !== null) {
try {
$extraField = trim((string)$extraField);
$address->setExtraField($extraField);
} catch (Exception $e) {
$this->logger->critical($e->getMessage());
}
}
}
}
Example/CheckoutFields/Observer/SaveAddressAttribute.php
<?php
namespace ExampleCheckoutFieldsObserver;
use MagentoFrameworkEventObserver;
use MagentoFrameworkEventObserverInterface;
use PsrLogLoggerInterface as Logger;
class SaveAddressAttribute implements ObserverInterface
{
/**
* @var Logger
*/
protected Logger $logger;
/**
* @param Logger $logger
*/
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
/**
* @param Observer $observer
* @return void
*/
public function execute(Observer $observer)
{
try {
$order = $observer->getEvent()->getOrder();
$quote = $observer->getEvent()->getQuote();
if (!$quote->isVirtual()) {
$order->getShippingAddress()->setExtraField($quote->getShippingAddress()->getExtraField());
}
$order->save();
} catch (Exception $e) {
$this->logger->critical($e->getMessage());
}
}
}