16

I need to create a customer programmatically in Magento 2, I haven't found much documentation around... basically what I need to do is translate the following code into "Magento 2":

$websiteId = Mage::app()->getWebsite()->getId();
$store = Mage::app()->getStore();

$customer = Mage::getModel("customer/customer");
$customer   ->setWebsiteId($websiteId)
            ->setStore($store)
            ->setFirstname('John')
            ->setLastname('Doe')
            ->setEmail('jd1@ex.com')
            ->setPassword('somepassword');

try{
    $customer->save();
}
2
  • you want to do this in a standalone script, or you have a model or something?
    – Marius
    Aug 10, 2015 at 5:28
  • @Marius, I have been working on this module and I have created a controller. It this controller I need to prepare some data to be saved and the idea is to call the customer model and save that information. The code above can be placed in a controller I would like to do the same but for Magento 2. I am still a bit confused with the new structure of Magento 2 and stuck here now.. I know It has something to do with class injections and object instances but I am not sure how to do it...
    – Eduardo
    Aug 10, 2015 at 15:06

5 Answers 5

29

Okay, after a while I found a solution in case someone else needs it.. Magento uses another approach to instantiate objects, the traditional way to instantiate objects in Magento 1.x was using "Mage::getModel(..)", this have changed in Magento 2. Now Magento uses an object manager to instantiate objets, I won't enter in details about how it works.. so, the equivalent code for creating customers in Magento 2 would look like this:

<?php

namespace ModuleNamespace\Module_Name\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action
{
    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @var \Magento\Customer\Model\CustomerFactory
     */
    protected $customerFactory;

    /**
     * @param \Magento\Framework\App\Action\Context      $context
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Customer\Model\CustomerFactory    $customerFactory
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Customer\Model\CustomerFactory $customerFactory
    ) {
        $this->storeManager     = $storeManager;
        $this->customerFactory  = $customerFactory;

        parent::__construct($context);
    }

    public function execute()
    {
        // Get Website ID
        $websiteId  = $this->storeManager->getWebsite()->getWebsiteId();

        // Instantiate object (this is the most important part)
        $customer   = $this->customerFactory->create();
        $customer->setWebsiteId($websiteId);

        // Preparing data for new customer
        $customer->setEmail("email@domain.com"); 
        $customer->setFirstname("First Name");
        $customer->setLastname("Last name");
        $customer->setPassword("password");

        // Save data
        $customer->save();
        $customer->sendNewAccountEmail();
    }
}

Hope this snippet of code help someone else..

11
  • 6
    You were very close. You should avoid using objectManager directly whenever possible--it's bad form. The proper way to do that is using dependency injection to get the 'factory' class, and use that to create an instance. If a factory class doesn't exist for a given class, it'll be auto-generated. I've edited your code to use this (added the factory to the constructor and class, and calling create()), and follow the PSR-2 code standards.
    – Ryan Hoerr
    Aug 10, 2015 at 23:02
  • Thanks for the correction @RyanH. I thought about using factory classes but wasn't sure how to, so I used objectManager... I will read more about PSR-2 code standards for future projects. I am using the code with your corrections now and everything work perfectly. Thanks
    – Eduardo
    Aug 12, 2015 at 1:11
  • @RyanH. Done ; )
    – Eduardo
    Aug 12, 2015 at 16:31
  • I can see it in databases but not for Admin panel. What happening?
    – Arni
    Dec 28, 2015 at 20:46
  • 2
    @Arni; my first guess is that you'd need to reindex :)
    – Asitis
    Sep 7, 2016 at 8:08
7

All the above examples will work, but according to the coding standards you should always use service contracts than the concrete classes.

Hence, the following way should be preferred for creating customer account programmatically.


use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Api\Data\CustomerInterfaceFactory;
use Magento\Store\Model\StoreManagerInterface;

class CustomerCreate
{
    public $store;

    public $customerFactory;

    public $customerRepository;

    public function __construct(
        StoreManagerInterface $store,
        CustomerInterfaceFactory $customerFactory,
        CustomerRepositoryInterface $customerRepository
    ) {
        $this->store = $store;
        $this->customerFactory = $customerFactory;
        $this->customerRepository = $customerRepository;
    }


    public function create()
    {
        try {
           /** @var \Magento\Customer\Api\Data\CustomerInterface $customer */
           $customer = $this->customerFactory->create();
           $customer->setStoreId($this->store->getStoreId());
           $customer->setWebsiteId($this->store->getWebsiteId());
           $customer->setEmail($email);
           $customer->setFirstname($firstName);
           $customer->setLastname($lastName);

           /** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository*/
           $customer = $this->customerRepository->save($customer);
           // Note: The save returns the saved customer object, else throws an exception.
       } catch (\Exception $e) {
          // Add log
       }
    }

}
3
  • Argument 1 passed to Magento\Customer\Model\ResourceModel\CustomerRepository\Interceptor::save() must be an instance of Magento\Customer\Api\Data\CustomerInterface, instance of Magento\Customer\Model\Customer\Interceptor given I get this error running the above code Mar 19, 2020 at 22:16
  • Hi, @BrandenB171 I have updated the complete code. It may be due to the use of customer model than customer API. Love an upvote if this works for you. Mar 21, 2020 at 9:02
  • 2
    That was it. I was not using CustomerInterfaceFactory, rather CustomerFactory, and that was returning the resource model Mar 22, 2020 at 16:45
4

Here is simple way to create a new customer with default group and current store.

use Magento\Framework\App\RequestFactory;
use Magento\Customer\Model\CustomerExtractor;
use Magento\Customer\Api\AccountManagementInterface;

class CreateCustomer extends \Magento\Framework\App\Action\Action
{
    /**
     * @var RequestFactory
     */
    protected $requestFactory;

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

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

    /**
     * @param \Magento\Framework\App\Action\Context $context
     * @param RequestFactory $requestFactory
     * @param CustomerExtractor $customerExtractor
     * @param AccountManagementInterface $customerAccountManagement
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        RequestFactory $requestFactory,
        CustomerExtractor $customerExtractor,
        AccountManagementInterface $customerAccountManagement
    ) {
        $this->requestFactory = $requestFactory;
        $this->customerExtractor = $customerExtractor;
        $this->customerAccountManagement = $customerAccountManagement;
        parent::__construct($context);
    }

    /**
     * Retrieve sources
     *
     * @return array
     */
    public function execute()
    {
        $customerData = [
            'firstname' => 'First Name',
            'lastname' => 'Last Name',
            'email' => 'customer@email.com',
        ];

        $password = 'MyPass123'; //set null to auto-generate

        $request = $this->requestFactory->create();
        $request->setParams($customerData);

        try {
            $customer = $this->customerExtractor->extract('customer_account_create', $request);
            $customer = $this->customerAccountManagement->createAccount($customer, $password);
        } catch (\Exception $e) {
            //exception logic
        }
    }
}
2
  • What is $request here?, can we add custom attributes also? Sep 5, 2018 at 14:51
  • How to set custom attributes ? Sep 6, 2018 at 7:27
0

This code run in external file or console file CLI Magento

namespace Company\Module\Console;

use Braintree\Exception;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\Framework\App\Bootstrap;


class ImportProducts extends Command
{

    public function magentoStart()
    {
        $startMagento = $this->bootstrap();
        $state = $startMagento['objectManager']->get('Magento\Framework\App\State');
        $state->setAreaCode('frontend');
        return $startMagento['objectManager'];
    }

    protected function bootstrap()
    {
        require '/var/www/html/app/bootstrap.php';
        $bootstrap = Bootstrap::create(BP, $_SERVER);
        $objectManager = $bootstrap->getObjectManager();
        return array('bootstrap' => $bootstrap, 'objectManager' => $objectManager);
    }

    protected function createCustomers($item)
    {
        $objectManager      = $this->magentoStart();
        $storeManager       = $objectManager->create('Magento\Store\Model\StoreManagerInterface');
        $customerFactory    = $objectManager->create('Magento\Customer\Model\CustomerFactory');

        $websiteId  = $storeManager->getWebsite()->getWebsiteId();
        $customer   = $customerFactory->create();
        $customer->setWebsiteId($websiteId);
        $customer->setEmail("eu@mailinator.com");
        $customer->setFirstname("First Name");
        $customer->setLastname("Last name");
        $customer->setPassword("password");
        $customer->save();
    }
}
0

The correct way to do this using modern Magento 2 interfaces is as follows. This will avoid deprecated function warnings:

    /**  @var CustomerInterfaceFactory $customerFactory */
    $customerFactory = $this->_bootstrap->getObjectManager()->get("\Magento\Customer\Api\Data\CustomerInterfaceFactory");

    $customer = $customerFactory->create();
    $customer->setWebsiteId(\ElectricLabs\MagentoHelpers::getCurrentStoreId());

    $customer->setEmail($emailAddress);
    $customer->setFirstname($firstName);
    $customer->setLastname($lastName);

    /**  @var CustomerRepositoryInterface $customerRepository */
    $customerRepository = $this->_bootstrap->getObjectManager()->get("\Magento\Customer\Api\CustomerRepositoryInterface");

    /**  @var Encryptor $encryptor */
    $encryptor = $this->_bootstrap->getObjectManager()->get("\Magento\Framework\Encryption\Encryptor");
    $passwordHash = $encryptor->getHash($password, true);
    $customer = $customerRepository->save($customer, $passwordHash);


    /**  @var SessionFactory $customerSessionFactory */
    $customerSessionFactory = $this->_bootstrap->getObjectManager()->get('Magento\Customer\Model\SessionFactory');
    $session = $customerSessionFactory->create();
    $session->setCustomerDataAsLoggedIn($customer);

    /**  @var EmailNotification $emailNotification */
    $emailNotification = $this->_bootstrap->getObjectManager()->get("\Magento\Customer\Model\EmailNotification");
    $emailNotification->newAccount($customer);
1
  • $this->_bootstrap->getObjectManager() is not good way to work with Magento ;) Oct 27, 2021 at 6:33

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.