With Magento 2, even the trivial task of adding a custom attribute to a Customer can become quite challenging.

Today I spent significant time to trace the issue and resolve it, so I want to share my experience with all current and future generations of Magento 2 developers to help to save some time.

First I created the upgrade script (based on Alan Storm’s Pestle) and added a code to create a custom ‘test_attribute’ to a Customer entity.


...... 
 
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
 
$customerEntity = $this->eavConfig->getEntityType('customer');
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
 
/** @var $attributeSet AttributeSet */
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
 
$eavSetup->addAttribute(\Magento\Customer\Model\Customer::ENTITY, 'test_attribute', [
    'user_defined' => true,
    'position' =>999,
    'type' => 'int',
    'label' => 'Test attribute',
    'input' => 'select',
    'sort_order' => 9999,
    'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
    'global' => 1,
    'default' => 0,
    'visible' => true,
    'required' => false,
    'group' => 'Account Information',
]);
 
$attribute = $this->eavConfig->getAttribute(\Magento\Customer\Model\Customer::ENTITY, 'test_attribute')
    ->addData([
        'attribute_set_id' => $attributeSetId,
        'attribute_group_id' => $attributeGroupId,
        'used_in_forms' => ['adminhtml_customer'],
    ]);
 
$attribute->save();
 
$eavSetup->updateAttribute(
    \Magento\Customer\Model\Customer::ENTITY,
    'test_attribute',
    'sort_order',
    9999
);


Everything seemed as working fine. When customer edit screen is opened, the attribute is there and I tried to save the customer with changed dropdown value

However, no matter how much I cleared the cache and tried switching attribute’s value from customer edit screen, it seems like it just not saving the attribute value at all.

Checked in the database if the attribute is properly added in the database, in “Default” attribute set and also in “adminhtml_customer” form.

Googling for the solution did not help either: https://goo.gl/u8Csok. It returned a bunch of results, but neither seemed like contains the real solution for the above issue.

Tracing the issue through the M2 code lead me to the class


"\Magento\Customer\Model\Metadata\CustomerMetadata".

The function getCustomAttributesMetadata is looping through all EAV attributes and checking if the attribute is marked as “is_system” inside the “customer_eav_attribute” table, which was the case with my custom attribute.

Solution:

By default, Magento flagged my custom attribute as is_system = 1, so I just needed to add ‘system’ => false in my upgrade script and execute it again (after I removed the original attribute directly from the database. ).


$eavSetup->addAttribute(\Magento\Customer\Model\Customer::ENTITY, 'force_pass_recovery', [
    'user_defined' => true,
    'position' =>999,
    'type' => 'int',
    'label' => 'Force Password Recovery Flag',
    'input' => 'select',
    'sort_order' => 9999,
    'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
    'global' => 1,
    'default' => 0,
    'visible' => true,
    'required' => false,
    'system' => false,
    'group' => 'Account Information',
]);

That set the is_system to 0 in the “customer_eav_attribute” table and enabled the saving of attribute value when the customer is saved from admin.

Hopefully, this can help someone to save some time tracing through Magento2 and wondering why the custom attribute is not saved from admin form.

Cheers