Magento 2: Create customer attributes programatically, without install script

After a long time and debugging and spent time on reading blogging site/forum I found the solution to create attribute in magento to programmatically and able to save value in this custom created attributes.

Here is mu complete code that works in my custom module:-

<?php
namespace Company\Mymodule\Helper;

use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;

class Customer extends \Magento\Framework\App\Helper\AbstractHelper
{
    /**
     * @var \Magento\Eav\Setup\EavSetupFactory
     */
    protected $eavEavSetupFactory;
    protected $eavConfig;
    protected $attributeSetFactory;

    public function __construct(
        ...
        \Magento\Eav\Setup\EavSetupFactory $eavEavSetupFactory,
        \Magento\Eav\Model\Config $eavConfig,       
        AttributeSetFactory $attributeSetFactory
        ...
    )
    {
        ...
        $this->eavEavSetupFactory = $eavEavSetupFactory;
        $this->attributeSetFactory = $attributeSetFactory;
        $this->eavConfig = $eavConfig;
        ...
    }   

    protected function createOrUpdateCustomerUDA($value, $input, $type)
    {
        /** @var CustomerSetup $customerSetup */
        $customerSetup = $this->eavEavSetupFactory->create();

        $customerEntity = $customerSetup->getEntityTypeId('customer');
        $attributeSetId = $customerSetup->getDefaultAttributeSetId($customerEntity);

        /** @var $attributeSet AttributeSet */
        $attributeSet = $this->attributeSetFactory->create();
        $attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
        $attributeCode = $this->getAttributeCode($value);

        $customerSetup->addAttribute(\Magento\Customer\Model\Customer::ENTITY, $attributeCode, [
            'type' => $type,
            'label' => $value,
            'input' => $input,
            'required' => false,
            'visible' => true,
            'user_defined' => true,
            'sort_order' => 90,
            'position' => 999,
            'system' => 0,
        ]);

        $attribute = $this->eavConfig->getAttribute(\Magento\Customer\Model\Customer::ENTITY, $attributeCode)
            ->addData([
                'attribute_set_id' => $attributeSetId,
                'attribute_group_id' => $attributeGroupId,
                'used_in_forms' => ['adminhtml_customer'],
            ]);

        $attribute->save();

        unset($customerSetup);      
    }

    protected function getAttributeCode($str)
    {
        return "pre_" . strtolower(str_replace(" ", "", $str));    
    } 
}

Please use above code and let me know if any issue. Happy coding :)


Try following code:

  1. app/code/[VendorName]/[ModuleName]/registration.php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    '[VendorName]_[ModuleName]',
    __DIR__
);
  1. app/code/[VendorName]/[ModuleName]/etc/module.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="[VendorName]_[ModuleName]" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Customer"/>
        </sequence>
    </module>
</config>
  1. app/code/[VendorName]/[ModuleName]/Setup/InstallData.php
namespace [VendorName]\[ModuleName]\Setup;

use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Customer\Model\Customer;
use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallData implements InstallDataInterface
{
    protected $customerSetupFactory;

    private $attributeSetFactory;

    public function __construct(
        CustomerSetupFactory $customerSetupFactory,
        AttributeSetFactory $attributeSetFactory
    ) {
        $this->customerSetupFactory = $customerSetupFactory;
        $this->attributeSetFactory = $attributeSetFactory;
    }

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);

        $customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
        $attributeSetId = $customerEntity->getDefaultAttributeSetId();

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

        $customerSetup->addAttribute(Customer::ENTITY, 'custom_username', [
            'type' => 'varchar',
            'label' => 'Custom Field',
            'input' => 'text',
            'user_defined' => false,
            'required' => false,
            'visible' => true,
            'sort_order' => 1000,
            'position' => 1000,
            'system' => 0,
        ]);

        $attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'custom_username')
        ->addData([
            'attribute_set_id' => $attributeSetId,
            'attribute_group_id' => $attributeGroupId,
            'used_in_forms' => ['adminhtml_customer'],
        ]);

        $attribute->save();
    }
}