skip to Main Content

I am writing a script to add values to a custom attribute for 10 thousand customers. I have two questions here.

  1. when we update custom attribute values for product, we can use:

    $resource = $product->getResource();
    $product->setData($attribute, $value);
    $resource->saveAttribute($product,$attribute);
    

which is very fast. But as for customer, it does not have getResource() method. The only way I know is: $this->_customerRepository->save($customer); which is very very slow. so how can I update the customers values faster?

  1. when I update these values in bulk, I wrote the script as followings, it was running fine at the first hundreds of customers data updating, but then throws exception:

    (/chroot/home/.../html/vendor/magento/framework/Exception/FileSystemException.php): failed to open stream: Too many open files in /chroot/home/.../html/vendor/composer/ClassLoader.php on line 444 
    

    I Googled this problem and someone says it is relevant to the settings of sever. However, since we rent the server and have no authorization to change it, how should I modify my code and make it use less resources?

    protected function updateAttributes($customersListData,$output) {
      $time_start = microtime(true);
      $totalLength = sizeof($customersListData);
      foreach ($customersListData as $customerIndex => $singleCustomerData) {
        try {
          $id = $singleCustomerData['id'];
          $customer = $this->_customerRepository->getById($id);
    
          $arrayKeys = array_keys($singleCustomerData);
          array_shift($arrayKeys);
          foreach ($arrayKeys as $singleKey) {
            if (empty($singleCustomerData[$singleKey])) {
              $singleCustomerData[$singleKey] = "";
            }
            $time_now = microtime(true);
            $time_used = $time_now - $time_start;
            $finished_records = (int)$customerIndex + 1;
            $output->writeln("Updating attribute: ".$singleCustomerData[$singleKey].". " .$finished_records ."/".$totalLength." done. will finsih in: ". round($time_used / $finished_records * ($totalLength - $finished_records), 0). "s.");
            $customer->setData($singleKey, $singleCustomerData[$singleKey]);
          }
          $this->_customerRepository->save($customer);
          unset($customer);
        } catch (Exception $e) {
          $output->writeln($e->getMessage());
          continue;
        }
      }
    }
    

2

Answers


    1. get All Customers before the “foreach” into a variable as array
    2. afterwards, you can pick your customer from the array instead of the repository
    3. make a $toUpdate[] array, where you put all your $customer objects
    4. at the end, outside of the foreach, you can bulk save all customers.

    in this case you have 2 Database requests per iteration in the foreach. this is like 20’000 requests within a minute or somewhat.

    Here an idea in pseudo-code:

    $allCustomers = $this->_customerRepository()->getAll();
    $bulkSave[];
    
    foreach($customersListData as $customerIndex => $singleCustomerData)
    {
        $myCustomer = $allCustomers->find($singleCustomerData['id']);
        $bulkSave[] = $myCustomer;
    }
    
    $this->_customerRepository()->save($bulkSave);
    
    Login or Signup to reply.
  1. Use bellow class in constructors

    MagentoFrameworkAppActionContext $context,
        MagentoFrameworkViewResultPageFactory $resultPageFactory,
        MagentoCustomerApiCustomerRepositoryInterface $customerRepositoryInterface
    
    public function execute()
      {
         $customerId = 2;
         if ($customerId) {
    
                $customer = $this->_customerRepositoryInterface->getById($customerId);
                $customer->setCustomAttribute('reward_barcode', $barcode);
                $this->_customerRepositoryInterface->save($customer);
    
       }
       $this->messageManager->addSuccess( __('Your membership successfully updated.') );
    }
    

    Alternative Faster Option

    You should use php programmatically out side magento and make database connection with that. Fetch data and update magento attributes. this will be faster and easy to update attributes.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search