How to create an editable customer attribute in Magento 2

In this article we will explore how to create a customer EAV attribute and how to control where is available in the store. In Commerce version store admins are able to add the attributes same as for other EAV types. For community version this feature is not available. Not to worry it very easy to add a customer attribute programmatically.

Before we start you can visit the official guide here. Keep in mind that the official guide mentions the following:

Both the save() and getResource() methods for Magento\Framework\Model\AbstractModel have been marked as @deprecated since 2.1 and should no longer be used.

However they do not provide an alternative for how to process the attributes. We will handle this part as well.

First thing you will need is an active module. We assume you are familiar on how to create one. Once you have that we will need to create a data patch script. If you are interested on more details about data patches you can visit another example here.\

Our data patches will reside in the following directory:

Techflarestudio\Attributes\Setup\Patch\Data
  • Our vendor and module name is Techflarestudio\Attributes
  • The patch files will reside in Setup\Patch\Data

Lets create our data patch class, we will call it AddCustomerCertificationAttribute.

<?php
/*
 *  @category	Techflarestudio
 *  @author		Wasalu Duckworth
 *  @copyright  Copyright (c) 2021 Techflarestudio, Ltd. 			(https://techflarestudio.com)
 *
 */

namespace Techflarestudio\Attributes\Setup\Patch\Data;

use Magento\Customer\Model\Attribute\Backend\Data\Boolean;
use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Customer\Setup\Patch\Data\UpdateIdentifierCustomerAttributesVisibility;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Customer\Model\ResourceModel\Attribute;

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

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

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

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

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

        /**
         * Add attribute
         */
        $customerSetup->addAttribute(
            Customer::ENTITY,
            'certification', // the attribute code
            [
                'type' => 'int', // database value type
                'label' => 'Certification', // Set the label
                'input' => 'boolean', // input type
                'backend' => Boolean::class, // backend model for boolean type attributes
                'position' => 100, // position in form
                'required' => false, // is it required for all customers?
                'system' => false, // is created by system
            ]
        );

        /**
         * Fetch the newly created attribute and set options to be used in forms
         */
        $certificationAttribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'certification');

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

        $this->attributeResource->save($certificationAttribute);

        return $this;
    }

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

    /**
     * @inheritdoc
     */
    public function getAliases()
    {
        return [];
    }
}
\Techflarestudio\Attributes\Setup\Patch\Data\AddCustomerCertificationAttribute

Couple of things to break down here:

        $customerSetup->addAttribute(
            Customer::ENTITY,
            'certification', // the attribute code
            [
                'type' => 'int', // database value type
                'label' => 'Certification', // Set the label
                'input' => 'boolean', // input type
                'backend' => Boolean::class, // backend model for boolean type attributes
                'position' => 100, // position in form
                'required' => false, // is it required for all customers?
                'system' => false, // is created by system
            ]
        );
\Techflarestudio\Attributes\Setup\Patch\Data\AddCustomerCertificationAttribute
  • The customerSetupFactory class allows us to instantiate a setup class
  • We are using addAttribute function to create a boolean type attribute, add sanitize backend class which cleans up the values, making sure the attribute is set as system false which will allow us to edit this in other forms.
        $certificationAttribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'certification');

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

        $this->attributeResource->save($certificationAttribute);
\Techflarestudio\Attributes\Setup\Patch\Data\AddCustomerCertificationAttribute
  • We will use Magento\Customer\Model\ResourceModel\Attribute to update the used_in_forms. Since the
  • We are using all available forms but you should keep this to minimum required. If you ever need you can create another data patch to update the available forms.

That is it. Make sure to enable your module using

bin/magento module:enable Techflarestudio_Attributes

Then execute the setup upgrade function to make sure our script is executed:

bin/magento setup:upgrade

Once that is done you can go to Magento admin -> Customers -> Create new customer and you will see the newly created Certification attribute.

In order to add this attribute to storefront you will need to adjust additional code - we will explore that in future articles.