Adding an extension attribute to the LokiCheckout is just as straight-forward as adding an EAV attribute. It is just that your database storage is not running via EAV, but via a customized extension attribute of your choice.
The following example assumes that you have already added your own etc/extension_attributes.xml
file to define a new extension attribute example
for the \Magento\Quote\Api\Data\AddressInterface
class. Also, we assume that you have found your way to load and save this extension attribute into the quote address, for instance, by adding a DI interceptor plugin to all methods of the \Magento\Quote\Api\CartRepositoryInterface
class.
Let's create a new block for this extension attribute via an XML layout file loki_checkout_block_shipping_address.xml
:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:View/Layout:etc/page_configuration.xsd">
<body>
<referenceBlock name="loki-checkout.shipping.address.form">
<block
name="loki-checkout-example.shipping.address.example" as="example"
template="Yireo_LokiFieldComponents::form/field.phtml"/>
</referenceBlock>
</body>
</page>
Note that the PHTML template Yireo_LokiFieldComponents::form/field.phtml
is reused here. Normally, this is what you want: A lot of changes you might want to make to this field can be made via either the ViewModel or the XML layout.
Within a file etc/loki_components.xml
, we are defining our block as a component, including a ViewModel and a repository. The ViewModel
is often quite generic, so we simply reuse a common class here. The repository is where the loading and saving of a field occurs - which is specific to our own extension attribute.
<?xml version="1.0" encoding="UTF-8" ?>
<components xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Yireo_LokiComponents:etc/loki_components.xsd">
<component
name="loki-checkout-example.shipping.address.example"
group="checkout"
viewModel="Yireo\LokiCheckout\Component\Base\Generic\CheckoutViewModel"
repository="Yireo\LokiCheckoutExample\Component\Checkout\Address\Example\ExampleRepository"
/>
</components>
Note that there is a group checkout
used here (it's definition can be found in the etc/loki_components.xml
file of the core module Yireo_LokiCheckout
) even though that group doesn't do much. You could also skip the group and add your own context
instead.
The repository class Yireo\LokiCheckoutExample\Component\Checkout\Address\Example\ExampleRepository
simply fetches the extension attribute from the quote and sets it back into the quote. Instead of creating the repository from scratch, you can fetch the quote and cart repository from the context.
namespace Yireo\LokiCheckoutExample\Component\Checkout\Example;
use Yireo\LokiFieldComponents\Component\Base\Field\FieldRepository;
use Yireo\LokiCheckout\Component\Base\Generic\CheckoutContext;
/**
* @method CheckoutContext getContext()
*/
class ExampleRepository extends FieldRepository
{
public function getValue(): mixed
{
return $this->getContext()->getQuote()->getExtensionAttributes()->getExample();
}
public function saveValue(mixed $value): void
{
$this->getContext()->getQuote()->getExtensionAttributes()->setExample($value);
$cartRepository = $this->getContext()->getCartRepository();
$cartRepository->save($quote);
}
}
Every time that your field is now modified, it should trigger an AJAX call, which is then calling upon your repository class, which then saves things to the database. It should just work :)