6

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.

  • do you have extension_attribute.xml – Amit Bera Apr 24 '17 at 2:54
  • @AmitBera: No I haven't added extension_attribute.xml . Can you highlight it's purpose? – amitshree Apr 24 '17 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 '17 at 7:02
  • @amitshree Please let me know if you have query for below posted answer. – Rakesh Jesadiya Apr 26 '17 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 '17 at 17:26
5
+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');
    }
2

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;
    }

}
  • 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 '17 at 14:59
  • 2
    $customer->getCustomAttribute('is_vendor')->getValue(); – Nahid Nov 12 '18 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.

  • I see attribute_set_id and attribute_group_id is set to 1 in eav_entity_attribute table for custom attributes. – amitshree Apr 26 '17 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 '17 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 '17 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 '17 at 6:14
  • Nice idea. I'll implement that. Thanks :) – amitshree Apr 29 '17 at 7:01
1

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;
    }

}
0

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

  • No it didn't worked. $customer->getCustomAttribute(); expects a parameter. – amitshree Apr 25 '17 at 13:54
  • @amitshree I have changed the method$customer->getCustomAttribute() to $customer->getCustomAttributes(). Now you can try. – Bojjaiah Apr 26 '17 at 5:27
  • Tried this. $customer->getCustomAttributes(); is empty for me. – amitshree Apr 26 '17 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 '17 at 5:21
  • I got it fixed following this magento.stackexchange.com/a/171958/9169 – amitshree Apr 28 '17 at 5:43
0

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, privacy policy and cookie policy

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