4

I have some problem to save custom customer entity attribute in database.
I've created a Patch to add this attribute to the customer entity. The attribute is shown correctly in the backend, but when I try to save it, the value doesn't save in the database.

My code is the following:

<?php
declare(strict_types=1);

namespace Ped\Referral\Setup\Patch\Data;

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

class AddCustomerReferralCodeAttribute implements DataPatchInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

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

    /**
     * @var AttributeRepositoryInterface
     */
    private $attributeRepository;

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

    /**
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        CustomerSetupFactory $customerSetupFactory,
        AttributeRepositoryInterface $attributeRepository,
        AttributeSetFactory $attributeSetFactory,
        EavSetupFactory $eavSetupFactory
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->customerSetupFactory = $customerSetupFactory;
        $this->attributeRepository = $attributeRepository;
        $this->attributeSetFactory = $attributeSetFactory;
        $this->eavSetupFactory = $eavSetupFactory;
    }

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

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

    /**
     * {@inheritdoc}
     * @return DataPatchInterface|void
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\StateException
     */
    public function apply()
    {
        $this->removeReferralCodeAttribute();
        $this->addReferralCodeAttribute();
    }

    /**
     * Remove referral_code customer attribute
     */
    private function removeReferralCodeAttribute()
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $eavSetup->removeAttribute(Customer::ENTITY, 'referral_code');
    }

    /**
     * Add referral_code customer attribute
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\StateException
     */
    private function addReferralCodeAttribute()
    {
        $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]);

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

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

        $customerSetup->addAttribute(
            Customer::ENTITY,
            'referral_code',
            [
                'type' => 'varchar',
                'label' => 'Referral Code',
                'input' => 'text',
                'required' => false,
                'sort_order' => 999,
                'position' => 999,
                'visible' => true,
                'default' => '',
                'user_defined' => true,
                'system' => 0,
                'unique' => true,
            ]
        );

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

        $this->attributeRepository->save($referralCodeAttribute);
    }
}

If I replace $this->attributeRepository->save($referralCodeAttribute); with $referralCodeAttribute->save() all works properly, but I don't want to use the save() method of attribute entity, because is deprecated.

I know that now I should use the resource model/api interface to save attribute, but in both cases, the attribute is showing on the admin panel, but when I try to save, it doesn't work. Why?

How can I use the resource model/api interface correctly to save the custom attribute?

3
  • did you try using Magento\Eav\Api\AttributeSetRepositoryInterface ?
    – fmsthird
    Commented Mar 19, 2019 at 9:20
  • No, I will try it and I'll say you if it works Commented Mar 19, 2019 at 9:31
  • I have modified your code, please check and let me know if it works or not
    – fmsthird
    Commented Mar 19, 2019 at 9:38

2 Answers 2

2

I found the solution by dump the ResourceModel classname used by the save() method that was deprecated in favor of service contract. The resource model that I should used is Magento\Customer\Model\ResourceModel\Attribute. Here the complete code:

<?php    
namespace Ped\Referral\Setup\Patch\Data;

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

class AddCustomerReferralCodeAttribute implements DataPatchInterface
{
    private const REFERRAL_CODE_FIELD_NAME = 'referral_code';

    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

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

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

    /**
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * @var AttributeResourceModel
     */
    private $attributeResourceModel;

    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        CustomerSetupFactory $customerSetupFactory,
        AttributeSetFactory $attributeSetFactory,
        EavSetupFactory $eavSetupFactory,
        AttributeResourceModel $attributeResourceModel
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->customerSetupFactory = $customerSetupFactory;
        $this->attributeSetFactory = $attributeSetFactory;
        $this->eavSetupFactory = $eavSetupFactory;
        $this->attributeResourceModel = $attributeResourceModel;
    }

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

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

    /**
     * {@inheritdoc}
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    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,
            static::REFERRAL_CODE_FIELD_NAME,
            [
                'type' => 'varchar',
                'label' => 'Referral Code',
                'input' => 'text',
                'required' => false,
                'sort_order' => 999,
                'position' => 999,
                'visible' => true,
                'default' => '',
                'user_defined' => true,
                'system' => 0,
                'unique' => true,
            ]
        );

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

        $this->attributeResourceModel->save($referralCodeAttribute);
    }

}
1

Try this one using Magento\Eav\Api\AttributeSetRepositoryInterface:

<?php
/*declare(strict_types=1);*/

namespace Ped\Referral\Setup\Patch\Data;

use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Eav\Api\AttributeRepositoryInterface;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Eav\Setup\EavSetupFactory;
//add this AttributeSetRepositoryInterface
use Magento\Eav\Api\AttributeSetRepositoryInterface;

class AddCustomerReferralCodeAttribute implements DataPatchInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

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

    /**
     * @var AttributeRepositoryInterface
     */
    private $attributeRepository;

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

    /**
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * @var $attribute
     */
    private $attribute;


    /**
     * AddCustomerReferralCodeAttribute constructor.
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param CustomerSetupFactory $customerSetupFactory
     * @param AttributeRepositoryInterface $attributeRepository
     * @param AttributeSetFactory $attributeSetFactory
     * @param EavSetupFactory $eavSetupFactory
     * @param AttributeSetRepositoryInterface $attribute
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        CustomerSetupFactory $customerSetupFactory,
        AttributeRepositoryInterface $attributeRepository,
        AttributeSetFactory $attributeSetFactory,
        EavSetupFactory $eavSetupFactory,
        AttributeSetRepositoryInterface $attribute
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->customerSetupFactory = $customerSetupFactory;
        $this->attributeRepository = $attributeRepository;
        $this->attributeSetFactory = $attributeSetFactory;
        $this->eavSetupFactory = $eavSetupFactory;
        $this->attribute = $attribute;
    }

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

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

    /**
     * {@inheritdoc}
     * @return DataPatchInterface|void
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\StateException
     */
    public function apply()
    {
        $this->removeReferralCodeAttribute();
        $this->addReferralCodeAttribute();
    }

    /**
     * Remove referral_code customer attribute
     */
    private function removeReferralCodeAttribute()
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $eavSetup->removeAttribute(Customer::ENTITY, 'referral_code');
    }

    /**
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    private function addReferralCodeAttribute()
    {
        $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]);

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

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

        $customerSetup->addAttribute(
            Customer::ENTITY,
            'referral_code',
            [
                'type' => 'varchar',
                'label' => 'Referral Code',
                'input' => 'text',
                'required' => false,
                'sort_order' => 999,
                'position' => 999,
                'visible' => true,
                'default' => '',
                'user_defined' => true,
                'system' => 0,
                'unique' => true,
            ]
        );

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

        //$this->attributeRepository->save($referralCodeAttribute);
        $this->attribute->save($referralCodeAttribute);
    }
}
1
  • No, it doesn't work, I receive this error: "Fatal error: Uncaught TypeError: Argument 1 passed to Magento\Eav\Model\AttributeSetRepository\Interceptor::save() must implement interface Magento\Eav\Api\Data\AttributeSetInterface, instance of Magento\Customer\Model\Attribute given, called in /var/www/html/app/code/Ped/Referral/Setup/Patch/Data/AddCustomerReferralCodeAttribute.php on line 138 and defined in /var/www/html/generated/code/Magento/Eav/Model/AttributeSetRepository/Interceptor.php:20" Commented Mar 19, 2019 at 10:22

Your Answer

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

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