3

I cannot save data for custom customer attributes in Magento2 admin.

I am creating custom Customer Attributes in a {customModule}/Setup/UpgradeData.php script. To execute it, I remove the entry for that module from the DB table setup_module (or update the module.xml version) and run bin/magento setup:upgrade from the command line. I have tried clearing the generation and other caches, re-indexing, etc.

This creates the custom attributes and displays them in admin>customer>edit, but it does not allow any data to be saved for that attribute. The same is true for custom attributes which were created by the migration tool. Standard attributes such as name or birthdate are editable. I have compared the data in tables eav_attribute, eav_form_element, customer_form_attribute and any others I can find but to no avail.

Can anyone see what is going wrong?

Here is the script:

<?php

namespace {Vendor}\{Module}\Setup;


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


class UpgradeData implements UpgradeDataInterface
{

private $customerSetupFactory;
private $attributeSetFactory;

public function __construct(
    \Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory,
    AttributeSetFactory $attributeSetFactory
    )
{
    $this->customerSetupFactory = $customerSetupFactory;
    $this->attributeSetFactory = $attributeSetFactory;


}


public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{   
    $attributeCode = "test";
    $installer = $setup;
    $installer->startSetup();

    $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);

    $customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
    $attributeSetId = $customerEntity->getDefaultAttributeSetId();
    $attributeSet = $this->attributeSetFactory->create();
    $attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);



    $customerSetup->removeAttribute(\Magento\Customer\Model\Customer::ENTITY, $attributeCode);

    $customerSetup->addAttribute(\Magento\Customer\Model\Customer::ENTITY, $attributeCode,  array(
        "type"     => "varchar",
        "backend"  => "",
        "label"    => $attributeCode.'label',
        "input"    => "text",
        "source"   => "",
        "visible"  => true,
        "required" => false,
        "default" => "",
        "frontend" => "",
        "unique"     => false,
        "note"       => "",
        "system"  => false,

    ));

 //Alternate to setting these id's to 1, I tried this:
 //$customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
 //$attributeSetId = $customerEntity->getDefaultAttributeSetId();
 //$attributeSet = $this->attributeSetFactory->create();
 //$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
 // 'attribute_set_id' => $attributeSetId,
 // 'attribute_group_id' => $attributeGroupId


    $my_attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, $attributeCode)
    ->setData([
        'attribute_set_id' => 1,
        'attribute_group_id' => 1,
        'used_in_forms' => ['adminhtml_customer'],
        'used_in_forms' => ['checkout_register'],
    'used_in_forms' => ['customer_account_create'],
    'used_in_forms' => ['customer_account_edit'],
    'used_in_forms' => ['adminhtml_checkout'],
    ]);

    $my_attribute->save();
    $installer->endSetup();

    }

}

Still working on this... I am checking what is saved in the DB with this query:

SELECT ea.attribute_id, ea.attribute_code, eea.`attribute_set_id`,  eea.`attribute_group_id`, efe.type_id, cea.is_system, ceaw.website_id,  cfa.form_code FROM eav_attribute as ea
inner join eav_entity_attribute as eea ON ea.attribute_id = eea.`attribute_id`
left join eav_form_element as efe ON ea.attribute_id = efe.`attribute_id`
left join customer_eav_attribute as cea ON ea.attribute_id = cea.attribute_id
left join customer_eav_attribute_website as ceaw ON ea.attribute_id =   ceaw.`attribute_id`
left join customer_form_attribute as cfa ON ea.attribute_id = cfa.attribute_id
WHERE ea.attribute_code IN ('testb', 'dob', 'lastname')
AND ea.entity_type_id=1     

(Both 'dob' and 'lastname' are attributes which do save). The only thing I see is that my test attribute is not affiliated with a website in customer_eav_attribute_website, but neither is 'dob'.

1 Answer 1

1

You have to keep below code inside your UpgradeData.php file,

<?php
/**
 * Copyright © 2015 Clounce. All rights reserved.
 * See LICENSE.txt for license details.
 */

namespace {Vendor}\{Module}\Setup;

use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Customer\Model\Customer;

class UpgradeData implements UpgradeDataInterface
{
    public function __construct(EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * Installs data for a module
     */
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        $attributes = [
            'test'=> [
                "type"     => "varchar",
                "label"    => "Your custom label",
                "input"    => "text",                
                'sort_order' => 100,
                "required" => false,
                'position' => 100,
                'system' => false,                
                //'validate_rules' => 'a:2:{s:15:"max_text_length";i:255;s:15:"min_text_length";i:1;}',
            ],
        ];

        foreach ($attributes as $code => $options) {
            $eavSetup->addAttribute(
                Customer::ENTITY,
                $code,
                $options
            );
        }

        $this->installCustomerForms($eavSetup);
    }

    /**
     * Add customer attributes to customer forms
     */
    public function installCustomerForms(EavSetup $eavSetup)
    {
        $customer = (int)$eavSetup->getEntityTypeId(\Magento\Customer\Model\Customer::ENTITY);
        /**
         * @var ModuleDataSetupInterface $setup
         */
        $setup = $eavSetup->getSetup();

        $attributeIds = [];
        $select = $setup->getConnection()->select()->from(
            ['ea' => $setup->getTable('eav_attribute')],
            ['entity_type_id', 'attribute_code', 'attribute_id']
        )->where(
            'ea.entity_type_id IN(?)',
            [$customer]
        );
        foreach ($eavSetup->getSetup()->getConnection()->fetchAll($select) as $row) {
            $attributeIds[$row['entity_type_id']][$row['attribute_code']] = $row['attribute_id'];
        }

        $data = [];

        $attributes = [
            'test'=> [
                "type"     => "varchar",
                "label"    => "Your custom label",
                "input"    => "text",                
                'sort_order' => 100,
                "required" => false,
                'position' => 100,
                'system' => false,                
                //'validate_rules' => 'a:2:{s:15:"max_text_length";i:255;s:15:"min_text_length";i:1;}',
            ],
        ];

        foreach ($attributes as $attributeCode => $attribute) {
            $attributeId = $attributeIds[$customer][$attributeCode];
            $attribute['system'] = isset($attribute['system']) ? $attribute['system'] : true;
            $attribute['visible'] = isset($attribute['visible']) ? $attribute['visible'] : true;
            if ($attribute['system'] != true || $attribute['visible'] != false) {
                $usedInForms = ['customer_account_create','adminhtml_customer','checkout_register','customer_account_edit','adminhtml_checkout'];

                foreach ($usedInForms as $formCode) {
                    $data[] = ['form_code' => $formCode, 'attribute_id' => $attributeId];
                }
            }
        }

        if ($data) {
            $setup->getConnection()->insertOnDuplicate($setup->getTable('customer_form_attribute'), $data);
        }
    }
}

Remove var folder from root and run command,

php bin/magento setup:upgrade

and

php bin/magento indexer:reindex

Check again. Its working.

4
  • I have been working with this new approach for an hour now [thank you very much for outlining a new approach!], but I still can't save any data. This code creates new attributes and I see their setup data correctly inserted into all the tables of which I am aware, but despite stringent cache clearing (now by actually deleting the var folder) and reindexing (which takes a while because of 200K customers) and newly logging in (just in case) the data entered in admin>customer>edit still does not save. Should a store code be entered? Something else?
    – Garruchal
    Apr 29, 2016 at 19:12
  • Still working on this... I've compared entries in the DB with this query:
    – Garruchal
    Apr 29, 2016 at 21:30
  • Yes, this works. The problem I encountered appears to have come from the migration tool. The custom attributes from Magento 1.9 were migrated to 2.0, but could not be saved. On a fresh install of Magento 2.0.5, with no migration, the above code works. I will try to track down the cause in the DB.
    – Garruchal
    May 2, 2016 at 18:04
  • How can i add for Customer address field for this same code? Jul 26, 2017 at 13:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.