Magento 2 – Add Custom Select to Customer Source Model

customermagento2modulesource-model

I added an attribute to customer entity

My goal is to have this attribute as Select (with data from another db table), but i didn't find any tuto about the source/model that i should create !!

Here is the Files :

InstallData Vendor/Module/Setup/InstallData.php

<?php
    namespace Vendor\Module\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;

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

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

        $customerSetup->addAttribute(Customer::ENTITY, 'testfield', [
            'type' => 'varchar',
            'label' => 'Test Field',
            'input' => 'select',
            'required' => false,
            'visible' => true,
            'user_defined' => true,
            'visible_on_front' => true, 
            'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
            'source' => \Vendor\Module\Model\Customer\Attribute\Source\Test,
        ]);

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

        $attribute->save();
    }
}

Source Model (Needed Code) : Vendor\Module\Model\Customer\Attribute\Source\Test

<?php
namespace Vendor\Module\Model\Customer\Attribute\Source;


class Test extends \Magento\Eav\Model\Entity\Attribute\Source\Table
{

    public function __construct(..........) 
{
        ......................
    }

    /**
     * @return array
     */
    public function getAllOptions()
    {
        ...................

        return $this->_options;
    }


}

Could any one help me how to create this source model.

Best Answer

Install Data

<?php
    namespace Vendor\Module\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;

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

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

        $customerSetup->addAttribute(Customer::ENTITY, 'testfield', [
            'type' => 'varchar',
            'label' => 'Test Field',
            'input' => 'select',
            'required' => false,
            'visible' => true,
            'user_defined' => true,
            'visible_on_front' => true, 
            'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
            'source' => Vendor\Module\Model\Customer\Attribute\Source\Test,
            'system' => 0,

        ]);

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

        $attribute->save();
    }
}

Source Model

<?php
namespace Vendor\Module\Model\Customer\Attribute\Source;

class Test extends \Magento\Eav\Model\Entity\Attribute\Source\Table
{
    public function getAllOptions()
    {
        $obj = \Magento\Framework\App\ObjectManager::getInstance();
        $helper = $obj->create('Vendor\Module\Helper\Data');
        $tags = $helper->getCollection();
        foreach($tags as $tag){
            $label = $tag->getTitle();
            $value = $tag->getTagsId();
            $option[] = array('label'=>$label,'value'=>$value);
        }
        $this->_options = $option;

        return $this->_options;
    }
}

Helper Data.php

protected $_tagsCollectionFactory;

public function __construct(
    \Magento\Framework\App\Helper\Context $context,
    \Vendor\Module\Model\ResourceModel\Tags\CollectionFactory $tagsCollectionFactory
) {
    $this->_tagsCollectionFactory = $tagsCollectionFactory;
    parent::__construct($context);
}

public function getCollection()
{
    $collection = $this->_tagsCollectionFactory->create();
    return $collection;
}

Note: Tags is for example. You can load your collection and return to getAllOptions function.

If your install data script successfully installed your custom attribute, now you just need to override addition information phtml file and set your custom attribute in that.

Create Vendor/Module/view/frontend/layout/customer_account_create.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
    <referenceContainer name="form.additional.info">
        <block class="Magento\Framework\View\Element\Template" name="additional_info_customer" template="Vendor_Module::attribute.phtml"/>
    </referenceContainer>
</body>
</page>

Create Vendor/Module/view/frontend/templates/attribute.phtml

<fieldset class="fieldset create account" data-hasrequired="<?php /* @escapeNotVerified */ echo __('* Required Fields') ?>">
    <legend class="legend"><span><?php /* @escapeNotVerified */ echo __('Additional Information') ?></span></legend>
    <p>
    <div class="field regulation">
        <label for="regulation" class="label"><span><?php /* @escapeNotVerified */
                echo __('Test Field') ?></span></label>
        <div class="control">
            <input type="text" name="testfield" id="testfield" title="<?php /* @escapeNotVerified */ echo __('Test Field') ?>" class="input-text" data-validate="{required:false}">
        </div>
    </div>
    </p>
</fieldset>
Related Topic