5

How to add an Attribute for a Customer Entity in a custom module using declarative schema in Magento 2.3?

2
  • You can create custom attribute in normal way also in 2.3. Did you try it? Dec 21, 2018 at 8:43
  • Yes i know. but i am asking how to create in declarative approach?
    – Pavithra
    Dec 22, 2018 at 4:31

4 Answers 4

7

Please use the following code to create Customer's Phone number attribute that will be used in the Registration form too:

<?php
namespace Vendor\Module\Setup\Patch\Data;

use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;

/**
 * Class AddCustomerPhoneNumberAttribute
 * @package Vendor\Module\Setup\Patch\Data
 */
class AddCustomerPhoneNumberAttribute implements DataPatchInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    protected $moduleDataSetup;

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

    /**
     * @var AttributeSetFactory
     */
    protected $attributeSetFactory;

    /**
     * AddCustomerPhoneNumberAttribute constructor.
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param CustomerSetupFactory $customerSetupFactory
     * @param AttributeSetFactory $attributeSetFactory
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        CustomerSetupFactory $customerSetupFactory,
        AttributeSetFactory $attributeSetFactory
    ){
        $this->moduleDataSetup = $moduleDataSetup;
        $this->customerSetupFactory = $customerSetupFactory;
        $this->attributeSetFactory = $attributeSetFactory;
    }

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

        $customerEntity = $customerSetup->getEavConfig()->getEntityType(Customer::ENTITY);
        $attributeSetId = $customerEntity->getDefaultAttributeSetId();

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

        $customerSetup->addAttribute(
            Customer::ENTITY,
            'phone_number',
            [
                'type' => 'varchar',
                'label' => 'Phone Number',
                'input' => 'text',
                'validate_rules' => '{"max_text_length":255,"min_text_length":1}',
                'required' => false,
                'sort_order' => 120,
                'position' => 120,
                'visible' => true,
                'user_defined' => true,
                'unique' => false,
                'system' => false,
            ]
        );

        $attribute = $customerSetup->getEavConfig()->getAttribute(
            Customer::ENTITY,
            'phone_number'
        );

        $attribute->addData(
            [
                'attribute_set_id' => $attributeSetId,
                'attribute_group_id' => $attributeGroupId,
                'used_in_forms' => ['adminhtml_customer', 'customer_account_create', 'customer_account_edit'],
            ]
        );

        $attribute->save();
    }

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

    /**
     * {@inheritdoc}
     */
    public function getAliases()
    {
        return [];
    }
}
3
  • I have implemented as explained. When I run setup:upgrade command it shows an error as follow:PHP Fatal error: Uncaught TypeError: Return value of Magento\Framework\Setup\Declaration\Schema\Declaration\SchemaBuilder::processTable() must be an instance of Magento\Framework\Setup\Declaration\Schema\Dto\Table, boolean returned in /var/www/html/magento231/lib/internal/Magento/Framework/Setup/Declaration/Schema/Declaration/SchemaBuilder.php:251 Jun 17, 2019 at 6:11
  • 1
    $attribute->save(); is deprecated, is there any alternative for the same?
    – Nidheesh
    Dec 3, 2019 at 7:47
  • @Nidheesh great question sir :) please check this github.com/magento/magento2/blob/2.3.4/app/code/Magento/…
    – M.Elwan
    Feb 24, 2021 at 0:56
1

I have added one customer attribute using Declarative Schema in a custom module.

<?php

namespace vendor_name\module_name\Setup\Patch\Data;

use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchVersionInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Framework\DB\Ddl\Table;

class AddTestAttribute implements DataPatchInterface
{
    protected $_moduleDataSetup;
    protected $_customerSetupFactory;
    protected $_attributeSetFactory;

    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        CustomerSetupFactory $customerSetupFactory,
        AttributeSetFactory $attributeSetFactory
    )
    {
        $this->_moduleDataSetup = $moduleDataSetup;
        $this->_customerSetupFactory = $customerSetupFactory;
        $this->_attributeSetFactory = $attributeSetFactory;
    }

    public function apply()
    {
        $customerSetup = $this->_customerSetupFactory->create(['setup' => $this->_moduleDataSetup]);

        $customerEntity = $customerSetup->getEavConfig()->getEntityType(Customer::ENTITY);
        $attributeSetId = $customerEntity->getDefaultAttributeSetId();

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

        $customerSetup->removeAttribute(Customer::ENTITY, 'test');
        $customerSetup->addAttribute(Customer::ENTITY, 'test', array(
            'type' => Table::TYPE_DECIMAL,
            'label' => 'Test',
            'input' => 'text',
            'required' => 0,
            'default' => 0,
            'visible' => 0,
            'system' => 0
        ));
    }

    public function getAliases()
    {
        return [];
    }

    public static function getDependencies()
    {
        return [

        ];
    }
}
4
  • 1
    its not displayed on form Mar 1, 2019 at 5:37
  • how can we make it visible on form Mar 1, 2019 at 6:01
  • i have changed visible 0 to 1 still its not visible on admin form Mar 1, 2019 at 6:02
  • @AdarshShukla - To display in form you need to add following code at the end of apply method: $sampleTestAttributeId = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'test'); $sampleTestAttributeId->addData( [ 'attribute_set_id' => $attributeSetId, 'attribute_group_id' => $attributeGroupId, 'used_in_forms' => ['adminhtml_customer', 'customer_account_create', 'customer_account_edit'] ] ); $sampleTestAttributeId->save(); Sep 6, 2019 at 12:18
0

After reviewing the schema.xsd; I don't see any support for it; but - you can add support for it by updating the schema in your own module and then pointing your file to it while adding support for the additional functionality. (which is alot of work unless you are building several modules and you are doing this within your "core")

Currently this is easily done the previous way via the InstallData.php; I'm not sure if anyone wants this added to declarative at this time; if so; I can put something together as a PR?

2
  • If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From Review
    – Jarnail S
    Jan 28, 2019 at 19:10
  • Upon some research; trying to add/remove attributes via declarative is short of crossing boundaries between the db schema and data patch demarcations. so technically; add/remove attributes should be done via installdata / data patches. Which @Ramanathan recommends.
    – billandr
    Jan 29, 2019 at 20:31
0

How would you go about adding multiple attributes? Is it as simple as

$newAttributes = ['attr1', attr2];
foreach($newAttributes as $attr){
    $customerSetup->removeAttribute(Customer::ENTITY, $attr);
}

With a similar foreach loop for every place where the name needs to be changed?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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