Hi,
I have made custom text attribute for customer (admin customer edit form) using installation script.
The attribute shows fine, but its not possible to save any value - seems that value not insets into customer_entity_varchar table.
Have you assigned it to the form? In #1238 there is a module setup example I've used to create a working custom customer attribute.
@sashas777, did you look at example from https://github.com/magento/magento2/issues/1238#issuecomment-105034397? Did you define 'used_in_forms' for this attribute?
@vpelipenko @Vinai
Hi,
Yes it is set 'used_in_forms' and it visible at the admin customer edit form. But when i enter information in the field it doesnt save it and put into customer_entity_varchar table. If i manually add record into table the values shows at the admin customer edit page.
Here is setup function from InstallData.php file:
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
/** @var CustomerSetup $customerSetup */
$customerSetup = $this->ExtensionSetupFactory->create(['setup' => $setup]);
$attributeParams=array(
'type' => 'varchar',
'label' => 'Customer Code',
'input' => 'text',
'required' => false,
'visible' => true,
'user_defined' => true,
'sort_order' => 90,
'position' => 90,
);
$customerSetup->addAttribute('customer', 'customer_code', $attributeParams);
$customerCodeAttribute = $customerSetup->getEavConfig()->getAttribute('customer', 'customer_code');
$customerCodeAttribute->setData(
'used_in_forms',
['adminhtml_customer']
);
$customerCodeAttribute->save();
}
Thanks
Internal ticket: MAGETWO-39121
@sashas777, we've investigated internal ticket and here is response:
Attribute is not possible to save any value, because the attribute data not stored in 'eav_entity_attribute' table.
To avoid this you must specify additional parameters for the attribute.
The 'system' parameter must be specified as 0 (the new attribute is not really system attribute).
The working code here (update VERSION to real module version value):
namespace Magento\Customer\Setup;
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\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class UpgradeData implements UpgradeDataInterface
{
/**
* @var CustomerSetupFactory
*/
protected $customerSetupFactory;
/**
* @var AttributeSetFactory
*/
private $attributeSetFactory;
/**
* @param CustomerSetupFactory $customerSetupFactory
* @param AttributeSetFactory $attributeSetFactory
*/
public function __construct(
CustomerSetupFactory $customerSetupFactory,
AttributeSetFactory $attributeSetFactory
) {
$this->customerSetupFactory = $customerSetupFactory;
$this->attributeSetFactory = $attributeSetFactory;
}
/**
* {@inheritdoc}
*/
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
if (version_compare($context->getVersion(), 'VERSION') < 0) {
/** @var CustomerSetup $customerSetup */
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
/** @var $attributeSet AttributeSet */
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
$customerSetup->addAttribute(Customer::ENTITY, 'customer_code', [
'type' => 'varchar',
'label' => 'Customer Code',
'input' => 'text',
'required' => false,
'visible' => true,
'user_defined' => true,
'sort_order' => 90,
'position' => 90,
'system' => 0,
]);
$attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'customer_code')
->addData([
'attribute_set_id' => $attributeSetId,
'attribute_group_id' => $attributeGroupId,
'used_in_forms' => ['adminhtml_customer'],
]);
$attribute->save();
}
}
}
Thanks. It works
I added this attribute in customer registration form. please let me know how to save this attribute form frontend.
I created attribute like this
webiste_url
I am trying to save this in
$customer->setWebsiteUrl(webiste_url);
also i tried to save it form front-end but notworking
I tried to save from backend but not working.
custom attribute created and display in customer form properly
<?php
namespace CustomModule\CustomCustomerModule\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;
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
/**
* @codeCoverageIgnore
*/
class InstallData implements InstallDataInterface
{
/**
* @var CustomerSetupFactory
*/
protected $customerSetupFactory;
/**
* @var AttributeSetFactory
*/
private $attributeSetFactory;
/**
* @param CustomerSetupFactory $customerSetupFactory
* @param AttributeSetFactory $attributeSetFactory
*/
public function __construct(
CustomerSetupFactory $customerSetupFactory,
AttributeSetFactory $attributeSetFactory
) {
$this->customerSetupFactory = $customerSetupFactory;
$this->attributeSetFactory = $attributeSetFactory;
}
/**
* {@inheritdoc}
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function install(
ModuleDataSetupInterface $setup,
ModuleContextInterface $context
) {
/** @var CustomerSetup $customerSetup */
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
/** @var $attributeSet AttributeSet */
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
/** @var CustomerSetup $customerSetup */
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$setup->startSetup();
$attributesInfo = [
'custom_ship_time_min' => [
'type' => 'varchar',
'label' => 'Shipping Time Min',
'input' => 'text',
'class' => '',
'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'filterable' => false,
'comparable' => false,
'unique' => false,
'position' => 119
],
'custom_ship_free' => [
'type' => 'int',
'label' => 'Shipping Free',
'input' => 'boolean',
'class' => '',
'backend' => 'Magento\Customer\Model\Attribute\Backend\Data\Boolean',
'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'filterable' => false,
'comparable' => false,
'unique' => false,
'position' => 121
]
];
foreach ($attributesInfo as $attributeCode => $attributeParams) {
$customerSetup->addAttribute(Customer::ENTITY, $attributeCode, $attributeParams);
$attribute = $customerSetup->getEavConfig()
->getAttribute(Customer::ENTITY, $attributeCode)
->addData(
[
'attribute_set_id' => $attributeSetId,
'attribute_group_id' => $attributeGroupId,
'used_in_forms'=> ['adminhtml_customer']
]
);
$attribute->save();
}
$setup->endSetup();
}
}
this worked with me
I tried to save it from backend but not working,
Magento only save the files of table customer_entity
@carloshernan007 Please try this one:
http://www.extensions.sashas.org/blog/magento-2-1-3-how-to-make-customer-attribute-update.html
@sashas777 In my form I see the new attributes of customer, but is impossible save the information of this attributes.
I checked the controller save the module customer in the line 215 the controller save the customer information with helper MagentoFrameworkReflectionMethodsMapDataObjectHelper in the line 98 the function _satDataValue the condition "$data Object instanceof CustomAttributesDataInterface" never is true I think that's reason of my problem.
`
protected function _setDataValues($dataObject, array $data, $interfaceName)
{
$dataObjectMethods = get_class_methods(get_class($dataObject));
foreach ($data as $key => $value) {
/* First, verify is there any setter for the key on the Service Data Object */
$camelCaseKey = \Magento\Framework\Api\SimpleDataObjectConverter::snakeCaseToUpperCamelCase($key);
$possibleMethods = [
'set' . $camelCaseKey,
'setIs' . $camelCaseKey,
];
if ($key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES
&& ($dataObject instanceof ExtensibleDataInterface)
&& is_array($data[$key])
&& !empty($data[$key])
) {
foreach ($data[$key] as $customAttribute) {
$dataObject->setCustomAttribute(
$customAttribute[AttributeInterface::ATTRIBUTE_CODE],
$customAttribute[AttributeInterface::VALUE]
);
}
} elseif ($methodNames = array_intersect($possibleMethods, $dataObjectMethods)) {
$methodName = array_values($methodNames)[0];
if (!is_array($value)) {
if ($methodName === 'setExtensionAttributes' && $value === null) {
// Cannot pass a null value to a method with a typed parameter
} else {
$dataObject->$methodName($value);
}
} else {
$getterMethodName = 'get' . $camelCaseKey;
$this->setComplexValue($dataObject, $getterMethodName, $methodName, $value, $interfaceName);
}
} elseif ($dataObject instanceof CustomAttributesDataInterface) {
$dataObject->setCustomAttribute($key, $value);
}
}
return $this;
}`
The files
vendor/magento/framework/Api/DataObjectHelper.php:98
vendor/magento/module-customer/Controller/Adminhtml/Index/Save.php:215
Maybe is necessary modified the class
@sashas777 In some point the controller saves the information of my customer attributes or write the data in the customer model, but never the save in my database I did check the table customer_entity_varchar all time is empty.
In the class AbstractExtensibleObject of file vendor/magento/framework/Api/AbstractExtensibleObject.php list all attributes included my custom attributes in the method setCustomAttribute.
@carloshernan007
You were correct. Thanks I did update to the article and checked - it works.
Thanks
Ok, thanks for your help
I followed the tutorial http://www.extensions.sashas.org/blog/magento-2-1-3-how-to-make-customer-attribute-update.html added the attributes that I needed, they are shown in the form, but when I save the changes they are not persited to the database.
When I register the information directly in the database, it is shown in the form, but when I save the changes, my custom information gets deleted.
@danielruedaa It should work. Have you tried to flush cache and switch to developer mode? Maybe you have the issue because of cache. The current code in the article works.
thanks for your help
For all of those that came here still searching for an answer:
When creating the customer attribute, please take care about following things:
It can be done by setting the attribute option to "system" => 0 in attribute parameters inside the install/upgrade script.
More about that particular issue can be found here.
@darkogoles1,
Tried as your comment, That didn't solve my issue, here is my stack link https://magento.stackexchange.com/questions/260079/multiselect-attribute-not-saving-in-magento-2-3-0
Customer Registration Custom attribute value create in admin and save
1. Text Field
2. Drop Down Field
3. Date Field
Using UpgradeSchema.php
<?php
namespace {CompanyName}\{ModuleName}\Setup;
use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetup;
/* irrelevant */
#use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
/* irrelevant */
#use Magento\Framework\Setup\SchemaSetupInterface;
/* add this */
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class UpgradeData implements UpgradeDataInterface
{
private $customerSetupFactory;
public function __construct(\Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory)
{
$this->customerSetupFactory = $customerSetupFactory;
}
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
if (version_compare($context->getVersion(), '1.0.1', '<'))
{
// For Text field
$customerSetup->addAttribute(
\Magento\Customer\Model\Customer::ENTITY,
'attribute_title',
[
'type' => 'text',
'input' => 'text',
'label' => 'Attribute Title',
'required' => false,
'visible' => true,
'user_defined' => false,
'sort_order' => 1000,
'position' => 1000,
'system' => 0,
]
);
$attribute_title = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'attribute_title')
->addData(
['used_in_forms' => ['adminhtml_customer']
]);
$attribute_title->save();
//Add field Drop Down for Yes/No
$customerSetup->addAttribute(
\Magento\Customer\Model\Customer::ENTITY,
'is_attribute',
[
'type' => 'int',
'input' => 'select',
'label' => 'Is Attribute',
'frontend' => '',
'default' => '1',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'required' => false,
'visible' => true,
'user_defined' => false,
'sort_order' => 1000,
'position' => 1000,
'system' => 0,
]
);
$is_attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'is_attribute')
->addData(
['used_in_forms' => ['adminhtml_customer']
]);
$is_attribute->save();
// For Date And Time field
$customerSetup->addAttribute(
\Magento\Customer\Model\Customer::ENTITY,
'custom_date',
[
'label' => 'Custom Date',
'type' => 'datetime',
'input' => 'date',
'frontend' => 'Magento\Eav\Model\Entity\Attribute\Frontend\Datetime',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\Datetime',
'validate_rules' => '{"input_validation":"date"}',
'user_defined' => false,
'required' => false,
'visible' => true,
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'sort_order' => 1000,
'position' => 1000,
'system' => 0,
]
);
$custom_date = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'custom_date')
->addData(
['used_in_forms' => ['adminhtml_customer']
]);
// more used_in_forms ['adminhtml_checkout','adminhtml_customer','adminhtml_customer_address','customer_account_edit','customer_address_edit','customer_register_address']
$commenced_business->save();
}
}
}
Basically I have been trying to add custom attribute in customer admin using upgrade data and customer setup. But here I can see in my db that my new custom attribute have been added successfully in eav_attribute,customer_eav_attribute,eav_entity_attribute,customer_grid_flat,customer_form_attribute also I am able to see that attribute in customer/admin/edit form in account information tab where I wanted to add. Also it is showing up in customer_grid filter with dropdown values also in customer_grid_table as new column. I am not getting any errors or warnings. Also my upgrade script is working properly its just not updating my custom attribute in eav_attribute_option and eav_attribute_option_value while rest of everything is working fine. I did cache clean, flush, upgrade and compile. I would really like to understand this concept and solve this issue any kind of suggestion would be great for me to continue learning. reindexing the whole magento 2 didn't work either. may I please get any guidance on this issue thanks
public function createSelectAttributeDataNewSignupReview($label = 'replace this value', $sortOrder = 1)
{
return [
'type' => 'int',
'store_label' => $label,
'frontend_label' => $label,
'input' => 'select',
'sort_order' => $sortOrder,
'required' => false,
'user_defined' => true,
'default' => null,
'system' => false,
'backend_type' => 'int',
'attribute_model' => 'Magento\Customer\Model\Attribute',
'visible' => true,
'visible_on_front' => true,
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL
];
}
public function getCustomAttributesData()
{
$sortOrder = 1;
$newsignupreview = $this->createSelectAttributeDataNewSignupReview('New Signup Review', $sortOrder++);
$newsignupreview['source'] = \Vendor\Customer\Model\Customer\Attribute\Source\NewSignupReview::class;
$newsignupreview['is_used_in_grid'] = true;
$newsignupreview['is_visible_in_grid'] = true;
$newsignupreview['is_filterable_in_grid'] = true;
$newsignupreview['is_searchable_in_grid'] = true;
return [
CustomerInterface::NEW_SIGNUP_REVIEW => $newsignupreview
];
}
public function addCustomAttributes()
{
$customAttributesData = $this->getCustomAttributesData();
$defaultUsedInForms = [
'adminhtml_customer',
'adminhtml_checkout',
'customer_account_create',
'customer_account_edit',
'checkout_register'
];
foreach ($customAttributesData as $attributeCode => $customAttributesDatum) {
$attributeId = $this->getAttributeId(Customer::ENTITY, $attributeCode);
if (empty($attributeId)) {
$this->addAttribute(Customer::ENTITY, $attributeCode, $customAttributesDatum);
}
$this->updateAttribute(Customer::ENTITY, $attributeCode, $customAttributesDatum);
$this->addAttributeToSet(
CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER,
null,
$attributeCode);
$attribute = $this->eavConfig->getAttribute(Customer::ENTITY, $attributeCode);
$usedInForms = null;
if ($attributeCode == CustomerInterface::REQUESTED_PASSWORD_RESET) {
$usedInForms = [
'adminhtml_customer'
];
}
$attribute->setData('used_in_forms', $usedInForms ? $usedInForms : $defaultUsedInForms);
$this->attributeResource->save($attribute);
}
}
\app\code\Company\Customer\Model\Customer\Attribute\Source\NewSignupReview.php
<?php
namespace Company\Customer\Model\Customer\Attribute\Source;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
use Company\Customer\Model\NewSignupReviewProvider;
class NewSignupReview extends AbstractSource
{
protected $newsignupreviewProvider;
protected $newsignupreviews;
public function __construct(NewSignupReviewProvider $newsignupreviewProvider)
{
$this->newsignupreviewProvider = $newsignupreviewProvider;
$this->newsignupreviews = $newsignupreviewProvider->getList();
}
public function getAllOptions()
{
if (!empty($this->_options)) {
return $this->_options;
}
$this->_options = [];
foreach ($this->newsignupreviews as $id => $label) {
$this->_options[] = [
'label' => __($label),
'value' => $id
];
}
return $this->_options;
}
}
md5-3112e366f6a16c5282b791c47dfd046d
\app\code\Company\Customer\Model\NewSignupReviewProvider.php
<?php
namespace Company\Customer\Model;
class NewSignupReviewProvider
{
public function getList($indexById = true)
{
$data = [
'' => 'Please select',
705 => 'Rejected',
706 => 'Unrejected'
];
if ($indexById) {
return $data;
}
$options = [];
foreach ($data as $id => $value) {
$options[] = [
'id' => $id,
'value' => $value
];
}
return $options;
}
}
you can check the articles to fix this issue, https://www.rakeshjesadiya.com/issue-customer-attribute-not-saving-value-in-admin-panel-magento-2/
Thanks @RakeshJesadiya , you saved my dayS!
Most helpful comment
@sashas777, we've investigated internal ticket and here is response:
Attribute is not possible to save any value, because the attribute data not stored in 'eav_entity_attribute' table.
To avoid this you must specify additional parameters for the attribute.
The 'system' parameter must be specified as 0 (the new attribute is not really system attribute).
The working code here (update VERSION to real module version value):