1

I want to know how does magento 2 control that email exist or not when creating an account because i have added a custom attribute so that the customer can log in with his custom attribute(login) or with email but i can't find a way to make the custom attribute unique i tried in installData and added the unique true but no result please any advice

2

vendor/magento/module-customer/Model/AccountManagement.php

public function createAccountWithPasswordHash(CustomerInterface $customer, $hash, $redirectUrl = '')
{

Check following code snippet:

// This logic allows an existing customer to be added to a different store.  No new account is created.
// The plan is to move this logic into a new method called something like 'registerAccountWithStore'
if ($customer->getId()) {
    $customer = $this->customerRepository->get($customer->getEmail());
    $websiteId = $customer->getWebsiteId();

    if ($this->isCustomerInStore($websiteId, $customer->getStoreId())) {
        throw new InputException(__('This customer already exists in this store.'));
    }
    // Existing password hash will be used from secured customer data registry when saving customer
}

In table customer_entity, email and website_id is unique.

[Update]

Create customer attribute and unique validation:

app/code/SR/MagentoCommunity/Setup/UpgradeData.php

<?php
namespace SR\MagentoCommunity\Setup;

use \Magento\Framework\Setup\UpgradeDataInterface;
use \Magento\Framework\Setup\ModuleContextInterface;
use \Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetup;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Eav\Model\Config as EavConfig;
use Magento\Eav\Setup\EavSetup;
use Magento\Customer\Model\ResourceModel\Attribute as CustomerAttributeResourceModel;

class UpgradeData implements UpgradeDataInterface
{
    /**
     * Customer setup factory
     *
     * @var \Magento\Customer\Setup\CustomerSetupFactory
     */
    private $customerSetupFactory;

    /**
     * @var EavConfig
     */
    private $eavConfig;

    /**
     * @var EavSetup
     */
    private $eavSetup;

    /**
     * @var CustomerAttributeResourceModel
     */
    private $customerAttributeResourceModel;

    /**
     * UpgradeData constructor.
     *
     * @param CustomerSetupFactory $customerSetupFactory
     * @param EavConfig $eavConfig
     * @param EavSetup $eavSetup
     * @param CustomerAttributeResourceModel $customerAttributeResourceModel
     */
    public function __construct(
        CustomerSetupFactory $customerSetupFactory,
        EavConfig $eavConfig,
        EavSetup $eavSetup,
        CustomerAttributeResourceModel $customerAttributeResourceModel
    ) {
        $this->customerSetupFactory = $customerSetupFactory;
        $this->eavConfig = $eavConfig;
        $this->eavSetup = $eavSetup;
        $this->customerAttributeResourceModel = $customerAttributeResourceModel;
    }

    /**
     * Upgrade data for a module
     *
     * @param ModuleDataSetupInterface $setup
     * @param ModuleContextInterface $context
     * @return void
     */
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {

        if (version_compare($context->getVersion(), '2.0.2', '<')) {
            $this->createUniqueAttribute($setup);
        }
    }

    /**
     * @param ModuleDataSetupInterface $setup
     */
    public function createUniqueAttribute($setup)
    {
        /** @var CustomerSetup $customerSetup */
        $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);

        // Add new customer attribute
        $customerSetup->addAttribute(
            Customer::ENTITY,
            'unique_mobile',
            [

                'label'                 => 'Unique Mobile',
                'input'                 => 'text',
                'required'              => false,
                'sort_order'            => 1000,
                'position'              => 1000,
                'visible'               => true,
                'system'                => false,
                'is_used_in_grid'       => false,
                'is_visible_in_grid'    => false,
                'is_filterable_in_grid' => false,
                'is_searchable_in_grid' => false,
                'default'               => '0',
                'user_defined' => false,
                'unique' => true,
                'backend' => 'SR\MagentoCommunity\Model\Customer\Attribute\Backend\UniqueMobile',
            ]
        );

        $attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'unique_mobile');
        $attribute->setData('used_in_forms', ['adminhtml_customer', 'customer_account_create', 'customer_account_edit']);
        $this->customerAttributeResourceModel->save($attribute);

        $setup->endSetup();
    }
}

app/code/SR/MagentoCommunity/Model/Customer/Attribute/Backend/UniqueMobile.php

<?php
namespace SR\MagentoCommunity\Model\Customer\Attribute\Backend;

use Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend;
use Magento\Customer\Model\ResourceModel\CustomerRepository;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Api\SearchCriteriaBuilderFactory;
use Magento\Framework\Exception\LocalizedException;

class UniqueMobile extends AbstractBackend
{
    /**
     * @var CustomerRepository
     */
    private $customerRepository;

    /**
     * @var SearchCriteriaBuilderFactory
     */
    private $searchCriteriaBuilderFactory;

    public function __construct(
        CustomerRepository $customerRepository,
        SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory
    ) {
        $this->customerRepository = $customerRepository;
        $this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory;
    }

    public function validate($customer)
    {
        $attributeName = $this->getAttribute()->getName();
        $inputValue = $customer->getData($attributeName);
        /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
        $searchCriteriaBuilder = $this->searchCriteriaBuilderFactory->create();
        $searchCriteriaBuilder->addFilter($attributeName, $inputValue, 'eq');
        if ($customer->getId()) {
            $searchCriteriaBuilder->addFilter('email', $customer->getEmail(), 'neq');
        }

        $searchCriteria = $searchCriteriaBuilder->create();
        $customers = $this->customerRepository->getList($searchCriteria)->getItems();
        if (count($customers) > 0) {
            $label = $this->getAttribute()->getFrontend()->getLabel();
            throw new LocalizedException(
                __('The "%1" attribute value is Unique. Set the another value and try again.', $label)
            );
        }
        return $this;
    }
}
  • thanks for your replay just one thing i already put my custom attribute as unique but why do i still not having error with two account with same custom attribute – Developper Magento Feb 26 at 16:02
  • is there a thing that i miss and i have to add – Developper Magento Feb 26 at 16:02
  • You need to check that before saving. You can add backend model for validation. Email is static attribute so it's easy to validate through MySQL validation. – Sohel Rana Feb 26 at 16:06
  • any example please and really thnaks a lot – Developper Magento Feb 26 at 16:19
  • Check updated answer – Sohel Rana Feb 26 at 17:34

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.