8

I've create a customer attribute using following installer data, InstallData.php file

<?php

namespace Amitshree\Marketplace\Setup;

use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
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;


class InstallData implements InstallDataInterface
{
    /*
     *  attribute to identify a customer is vendor or not
     */
    const IS_VENDOR = 'is_vendor';
  /**
     * @var EavSetupFactory
     */
    private $eavSetupFactory;


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

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

    /**
     * @param CustomerSetupFactory $customerSetupFactory
     * @param AttributeSetFactory $attributeSetFactory
     */
    public function __construct(
        EavSetupFactory $eavSetupFactory,
        CustomerSetupFactory $customerSetupFactory,
        AttributeSetFactory $attributeSetFactory
    ) {
        $this->eavSetupFactory = $eavSetupFactory;
        $this->customerSetupFactory = $customerSetupFactory;
        $this->attributeSetFactory = $attributeSetFactory;
    }
  public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();
    .......... //snip
    $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);

        /**
         *  create customer attribute is_vendor
         */
        $customerSetup->addAttribute(Customer::ENTITY, self::IS_VENDOR,
            [
            'type' => 'int',
            'label' => 'Is Vendor?',
            'input' => 'select',
            "source"   => "Amitshree\Marketplace\Model\Config\Source\CustomerYesNoOptions",
            'required' => false,
            'default' => '0',
            'visible' => true,
            'user_defined' => true,
            'sort_order' => 210,
            'position' => 210,
            'system' => false,
        ]);

        $is_vendor = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, self::IS_VENDOR)
            ->addData([
                'attribute_set_id' => $attributeSetId,
                'attribute_group_id' => $attributeGroupId,
                'used_in_forms' => ['adminhtml_customer','checkout_register','customer_account_create','customer_account_edit','adminhtml_checkout'],
            ]);

        $is_vendor->save();
......... //snip
$setup->endSetup();

I see attribute is properly created in customer section. Now when I'm trying to get value of this attribute in a controller, it doesn't return anything

<?php

namespace Amitshree\Marketplace\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action
{
    protected $resultPageFactory;
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
    \Magento\Customer\Api\CustomerRepositoryInterface $customerRepositoryInterface
    ) {
        $this->customerRepositoryInterface = $customerRepositoryInterface;
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }
    public function execute()
    {
        $customer =$this->customerRepositoryInterface->getById(5);
        print_r($customer->getCustomAttribute('is_vendor')->getValue());
    }
}

Also print_r($customer->getCustomAttributes()); returns an empty array. What I'm missing here.

5
  • do you have extension_attribute.xml
    – Amit Bera
    Apr 24, 2017 at 2:54
  • @AmitBera: No I haven't added extension_attribute.xml . Can you highlight it's purpose?
    – amitshree
    Apr 24, 2017 at 6:40
  • 1
    Your code is working perfectly fine for me. Have you tried and saved is_vendor value for customer_id 5 once. I mean just try and change the value of is_vendor attribute and save that customer. Now execute your code, i hope you should get the value. If you have not followed above process then you will get empty array because that attribute did not have any value set for those customer id in database.
    – arushi
    Apr 26, 2017 at 7:02
  • @amitshree Please let me know if you have query for below posted answer. Apr 26, 2017 at 8:27
  • @arushi: You are right. I just saved that customer and I'm able to get attribute value now. Any idea why this issue? I have default attribute value set to 0 in the installer and I'll not open and save all customers manually to fix this issue. Also Kindly write your comment in the answer section.
    – amitshree
    Apr 26, 2017 at 17:26

6 Answers 6

11
+50

Your code is working perfectly fine for me. The issue must be with no value for that attribute with the particular customer_is. Have you tried and saved is_vendor value for customer_id 5 once. I mean just try and change the value of is_vendor attribute and save that customer. Now execute your code, i hope you should get the value. If you have not followed above process then you will get empty array because that attribute did not have any value set for those customer id in database.

This is not an issue I must say, magento always work like that only, if you will create a new customer then things will work fine because customer form has that attribute and it will save its default value but already created customer did not have that attribute known to them, thus you need to write a small script to save all customer that were created previously and set whatever value you want for them.(this will be just one time process).

Below code will do the work:-

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$customerObj = $objectManager->create('Magento\Customer\Model\Customer')->getCollection();
foreach ($customerObj as $customerObjdata) {
    $customermodel  = $objectManager->create('Magento\Customer\Model\Customer');
    $customerData = $customermodel->getDataModel();
    $customerData->setId($customerObjdata->getData('entity_id'));
    $customerData->setCustomAttribute('is_vendor', 0);
    $customermodel->updateData($customerData);
            
    $customerResource = $objectManager->create('\Magento\Customer\Model\ResourceModel\CustomerFactory')->create();
    $customerResource->saveAttribute($customermodel, 'is_vendor');
}
4

You can get all customer custom attribute using below way,

Just replace your code with below one and remove var/generation folder and clear system cache and check.

<?php
namespace Amitshree\Marketplace\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action
{
    protected $resultPageFactory;

    public function __construct(        
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Magento\Customer\Api\CustomerRepositoryInterface $customerRepositoryInterface
    ) {  
        $this->resultPageFactory = $resultPageFactory;
        $this->customerRepositoryInterface = $customerRepositoryInterface;
        parent::__construct($context);
    }

    public function execute()
    {
        $customerId = 5;
        $customer = $this->customerRepositoryInterface->getById($customerId);
        $customerAttributeData = $customer->__toArray();
        $isVendor = $customerAttributeData['custom_attributes']['is_vendor']['value'];
        echo "<pre>";print_r($customerAttributeData['custom_attributes']);exit;
    }

}
2
  • Tried this. It says Undefined index: custom_attributes. I did print_r($customerAttributeData); and doesn't show custom_attributes array. It's only showing basic customer info (id, email, etc).
    – amitshree
    Apr 26, 2017 at 14:59
  • 6
    $customer->getCustomAttribute('is_vendor')->getValue();
    – Nahid
    Nov 12, 2018 at 8:06
1

I had the same problem and it was the value of attribute_set_id and attribute_group_id. You can create a custom attribute from admin. After, you must check, in the database, the value of this fields. You will see that the value attribute_set_id and attribute_group_id of this new attribute are different to created by code.

5
  • I see attribute_set_id and attribute_group_id is set to 1 in eav_entity_attribute table for custom attributes.
    – amitshree
    Apr 26, 2017 at 17:24
  • Are the values same for the attributes created from code and from admin panel? If this values are differents, you must do upgrading the attribute_set_id and attribute_group_id with the valid values.
    – raumatbel
    Apr 26, 2017 at 19:04
  • As per the comment by Arushi I just saved that customer and I'm able to get attribute value now. but the issue is that if customer is not saved once after this attribute creation, this attribute is not present in custom attributes (on program level) for this particular customer.
    – amitshree
    Apr 26, 2017 at 19:12
  • 1
    You can make a script (upgrade or cli) to save all the clients. This way you would already have all the clients with that attribute.
    – raumatbel
    Apr 29, 2017 at 6:14
  • Nice idea. I'll implement that. Thanks :)
    – amitshree
    Apr 29, 2017 at 7:01
1

change your method

public function execute()
    {
        $customer =$this->customerRepositoryInterface->getById(5);
        print_r($customer->getCustomAttribute('is_vendor')->getValue());
    }

to

public function execute()
    {
        $customer =$this->customerRepositoryInterface->getById(5);
        $customerCustomAttributes = $customer->getCustomAttributes();
        $isVendor = $customerCustomAttributes['is_vendor'];
        if($isVendor->getAttributecode() == "is_vendor"){
            $isVendorValue = $isVendor->getValue();
        }
    }

see below screenshot I can get the values.

enter image description here

5
  • No it didn't worked. $customer->getCustomAttribute(); expects a parameter.
    – amitshree
    Apr 25, 2017 at 13:54
  • @amitshree I have changed the method$customer->getCustomAttribute() to $customer->getCustomAttributes(). Now you can try.
    – Bojjaiah
    Apr 26, 2017 at 5:27
  • Tried this. $customer->getCustomAttributes(); is empty for me.
    – amitshree
    Apr 26, 2017 at 15:18
  • @amitshree in this case your custom attribute have value? if yes it will return value, other wise it will not return even null/empty. So you should check with your custom attribute have value or not?
    – Bojjaiah
    Apr 28, 2017 at 5:21
  • I got it fixed following this magento.stackexchange.com/a/171958/9169
    – amitshree
    Apr 28, 2017 at 5:43
0

You can get and set attribute and save.

    <?php

/**
 *
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Custom\OverrideCustomer\Controller\Account;

use Magento\Customer\Model\AuthenticationInterface;
use Magento\Customer\Model\Customer\Mapper;
use Magento\Customer\Model\EmailNotificationInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Data\Form\FormKey\Validator;
use Magento\Customer\Api\AccountManagementInterface;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Model\CustomerExtractor;
use Magento\Customer\Model\Session;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\InvalidEmailOrPasswordException;
use Magento\Framework\Exception\State\UserLockedException;

/**
 * Class EditPost
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class EditPost extends \Magento\Customer\Controller\Account\EditPost {

    /**
     * Form code for data extractor
     */
    const FORM_DATA_EXTRACTOR_CODE = 'customer_account_edit';

    /**
     * @var AccountManagementInterface
     */
    protected $customerAccountManagement;

    /**
     * @var CustomerRepositoryInterface
     */
    protected $customerRepository;

    /**
     * @var Validator
     */
    protected $formKeyValidator;

    /**
     * @var CustomerExtractor
     */
    protected $customerExtractor;

    /**
     * @var Session
     */
    protected $session;

    /**
     * @var \Magento\Customer\Model\EmailNotificationInterface
     */
    private $emailNotification;

    /**
     * @var AuthenticationInterface
     */
    private $authentication;

    /**
     * @var Mapper
     */
    private $customerMapper;



    /**
     * Change customer email or password action
     *
     * @return \Magento\Framework\Controller\Result\Redirect
     */
    public function execute() {
        /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultRedirectFactory->create();
        $validFormKey = $this->formKeyValidator->validate($this->getRequest());

        if ($validFormKey && $this->getRequest()->isPost()) {

            $currentCustomerDataObject = $this->getCustomerDataObject($this->session->getCustomerId());

            $customerCandidateDataObject = $this->populateNewCustomerDataObject(
                    $this->_request, $currentCustomerDataObject
            );

            try {
                // whether a customer enabled change email option
                $this->processChangeEmailRequest($currentCustomerDataObject);

                // whether a customer enabled change password option
                $isPasswordChanged = $this->changeCustomerPassword($currentCustomerDataObject->getEmail());

                //Custom Attribute get and set
                if ($currentCustomerDataObject->getCustomAttribute('am_is_activated')->getValue()) {
                    $customerCandidateDataObject->getCustomAttribute('am_is_activated')->setValue('1');
                }
                //save custom attribute
                $this->customerRepository->save($customerCandidateDataObject);
                $this->getEmailNotification()->credentialsChanged(
                        $customerCandidateDataObject,
                        $currentCustomerDataObject->getEmail(),
                        $isPasswordChanged
                );
                $this->dispatchSuccessEvent($customerCandidateDataObject);
                $this->messageManager->addSuccess(__('Your account information has been successfully updated.'));
                return $resultRedirect->setPath('customer/account');
            } catch (InvalidEmailOrPasswordException $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (UserLockedException $e) {
                $message = __(
                        'You did not sign in correctly or your account is temporarily disabled.'
                );
                $this->session->logout();
                $this->session->start();
                $this->messageManager->addError($message);
                return $resultRedirect->setPath('customer/account/login');
            } catch (InputException $e) {
                $this->messageManager->addError($e->getMessage());
                foreach ($e->getErrors() as $error) {
                    $this->messageManager->addError($error->getMessage());
                }
            } catch (\Magento\Framework\Exception\LocalizedException $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (\Exception $e) {
                $this->messageManager->addException($e,
                        __('We can\'t save the customer.'));
            }

            $this->session->setCustomerFormData($this->getRequest()->getPostValue());
        }

        return $resultRedirect->setPath('*/*/edit');
    }

    /**
     * Account editing action completed successfully event
     *
     * @param \Magento\Customer\Api\Data\CustomerInterface $customerCandidateDataObject
     * @return void
     */
    private function dispatchSuccessEvent(\Magento\Customer\Api\Data\CustomerInterface $customerCandidateDataObject) {
        $this->_eventManager->dispatch(
                'customer_account_edited',
                ['email' => $customerCandidateDataObject->getEmail()]
        );
    }

    /**
     * Get customer data object
     *
     * @param int $customerId
     *
     * @return \Magento\Customer\Api\Data\CustomerInterface
     */
    private function getCustomerDataObject($customerId) {
        return $this->customerRepository->getById($customerId);
    }

    /**
     * Create Data Transfer Object of customer candidate
     *
     * @param \Magento\Framework\App\RequestInterface $inputData
     * @param \Magento\Customer\Api\Data\CustomerInterface $currentCustomerData
     * @return \Magento\Customer\Api\Data\CustomerInterface
     */
    private function populateNewCustomerDataObject(
    \Magento\Framework\App\RequestInterface $inputData,
    \Magento\Customer\Api\Data\CustomerInterface $currentCustomerData
    ) {
        $attributeValues = $this->getCustomerMapper()->toFlatArray($currentCustomerData);
        $customerDto = $this->customerExtractor->extract(
                self::FORM_DATA_EXTRACTOR_CODE, $inputData, $attributeValues
        );
        $customerDto->setId($currentCustomerData->getId());
        if (!$customerDto->getAddresses()) {
            $customerDto->setAddresses($currentCustomerData->getAddresses());
        }
        if (!$inputData->getParam('change_email')) {
            $customerDto->setEmail($currentCustomerData->getEmail());
        }

        return $customerDto;
    }

    /**
     * Change customer password
     *
     * @param string $email
     * @return boolean
     * @throws InvalidEmailOrPasswordException|InputException
     */
    protected function changeCustomerPassword($email) {
        $isPasswordChanged = false;
        if ($this->getRequest()->getParam('change_password')) {
            $currPass = $this->getRequest()->getPost('current_password');
            $newPass = $this->getRequest()->getPost('password');
            $confPass = $this->getRequest()->getPost('password_confirmation');
            if ($newPass != $confPass) {
                throw new InputException(__('Password confirmation doesn\'t match entered password.'));
            }

            $isPasswordChanged = $this->customerAccountManagement->changePassword($email,
                    $currPass, $newPass);
        }

        return $isPasswordChanged;
    }

    /**
     * Process change email request
     *
     * @param \Magento\Customer\Api\Data\CustomerInterface $currentCustomerDataObject
     * @return void
     * @throws InvalidEmailOrPasswordException
     * @throws UserLockedException
     */
    private function processChangeEmailRequest(\Magento\Customer\Api\Data\CustomerInterface $currentCustomerDataObject) {
        if ($this->getRequest()->getParam('change_email')) {
            // authenticate user for changing email
            try {
                $this->getAuthentication()->authenticate(
                        $currentCustomerDataObject->getId(),
                        $this->getRequest()->getPost('current_password')
                );
            } catch (InvalidEmailOrPasswordException $e) {
                throw new InvalidEmailOrPasswordException(__('The password doesn\'t match this account.'));
            }
        }
    }

    /**
     * Get Customer Mapper instance
     *
     * @return Mapper
     *
     * @deprecated 100.1.3
     */
    private function getCustomerMapper() {
        if ($this->customerMapper === null) {
            $this->customerMapper = ObjectManager::getInstance()->get(\Magento\Customer\Model\Customer\Mapper::class);
        }
        return $this->customerMapper;
    }

}
-1

Custom attributes can also be obtained using getData() method.

Below example fetches a customer custom attribute, custom_attribute_name, in an observer.

namespace Company\Module\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;
use Magento\Customer\Api\CustomerRepositoryInterface;

class EnablePaymentMethodByCustomerAttribute implements ObserverInterface
{
    /** @var CustomerRepositoryInterface */
    protected $_customerRepository;
    protected $_logger;

    /**
     * 
     * @param CustomerRepositoryInterface $customerRepository
     * @param \Psr\Log\LoggerInterface $logger
     */
    public function __construct(
        CustomerRepositoryInterface $customerRepository,
        \Psr\Log\LoggerInterface $logger
    )
    {
        $this->_customerRepository = $customerRepository;
        $this->_logger = $logger;
    }

    /**
     * 
     * @param Observer $observer
     */
    public function execute(Observer $observer)
    {
        $customer = $observer->getCustomer();
        $customer->getData('custom_attribute_name');
    }
}

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.