In this article we will explore the necessary requirements to create a custom address attribute which will be used in customer addresses. The creation of these is very similar to how you would create a simple customer attribute. You can read further on that here - how to create a customer attribute.

There are only a few things we need to know before starting. All customer addresses have the same attribute sets - this means that the field you add will show in both shipping and billing addresses by default. We will look into how you can work around this in future articles.

As always we will create a data patch to create our attribute.

<?php
/*
 *  @category	Techflarestudio
 *  @author		Wasalu Duckworth
 *  @copyright  Copyright (c) 2021 Techflarestudio, Ltd. 			(https://techflarestudio.com)
 *  @license	http://opensource.org/licenses/OSL-3.0 The Open Software License 3.0 (OSL-3.0)
 *
 */

namespace Techflarestudio\Checkout\Setup\Patch\Data;

use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Customer\Model\ResourceModel\Attribute;

/**
 * Class AddAddressCustomAttribute
 * @package Techflarestudio\Checkout\Setup\Patch\Data
 */
class AddAddressCustomAttribute implements DataPatchInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

    /**
     * @var CustomerSetupFactory
     */
    private $customerSetupFactory;

    /**
     * @var AttributeSetFactory
     */
    private $attributeSetFactory;

    /**
     * @var Attribute
     */
    private $attribute;

    /**
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param CustomerSetupFactory $customerSetupFactory
     * @param AttributeSetFactory $attributeSetFactory
     * @param Attribute $attribute
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        CustomerSetupFactory $customerSetupFactory,
        AttributeSetFactory $attributeSetFactory,
        Attribute $attribute
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->customerSetupFactory = $customerSetupFactory;
        $this->attributeSetFactory = $attributeSetFactory;
        $this->attribute = $attribute;
    }

    /**
     * @inheritdoc
     */
    public function apply()
    {
        $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $customerAddressEntity = $customerSetup->getEavConfig()->getEntityType('customer_address');
        $attributeSetId = $customerAddressEntity->getDefaultAttributeSetId();

        $attributeSet = $this->attributeSetFactory->create();
        $attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);

        $customerSetup->addAttribute('customer_address', 'custom_field', [
            'type'          => 'varchar',
            'label'         => 'TFC Custom Field',
            'input'         => 'text',
            'required'      =>  false,
            'visible'       =>  true,
            'user_defined'  =>  true,
            'sort_order'    =>  13,
            'position'      =>  13,
            'system'        =>  0,
        ]);


        $attribute = $customerSetup->getEavConfig()->getAttribute('customer_address', 'custom_field');

        $attribute->setData('used_in_forms', [
            'adminhtml_customer',
            'adminhtml_checkout',
            'adminhtml_customer_address',
            'customer_account_edit',
            'customer_address_edit',
            'customer_register_address',
        ]);
        
        $this->attribute->save($attribute);


        return $this;
    }

    /**
     * @inheritdoc
     */
    public static function getDependencies()
    {
        return [];
    }

    /**
     * @inheritdoc
     */
    public function getAliases()
    {
        return [];
    }
}
\Techflarestudio\Checkout\Setup\Patch\Data\AddAddressCustomAttribute
  • The same as for regular customer attributes we are using CustomerSetupFactory to instantiate the setup class
  • One caveat for address specific fields is that in addAttribute function we need to pass in customer_address. This is required so that attribute would be added in the correct area.
  • In addition we are adding attribute set and attribute group id which we get from customer_address entity.
  • A very important part here is to set the used_in_forms.

In the following articles we will show you how to include this field in checkout shipping and billing addresses, how to validate and save it.