如何更快更有效地更新客户数据

How to update customer data faster and more efficiently

我正在编写一个脚本来为 10,000 个客户的自定义属性添加值。我有两个问题。

  1. 当我们更新产品的自定义属性值时,我们可以使用:

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

这是非常快的。但是对于客户来说,它没有 getResource() 方法。我知道的唯一方法是: $this->_customerRepository->save($customer);这是非常非常慢的。那么我怎样才能更快地更新客户的价值呢?

  1. 当我批量更新这些值时,我编写了如下脚本,在前数百个客户数据更新时运行没问题,但随后抛出异常:

    (/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 
    

    我google了一下这个问题,有人说是跟服务器的设置有关。但是,由于我们租用了服务器,没有权限更改,我应该如何修改我的代码,使其使用更少的资源?

    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;
        }
      }
    }
    
  1. 将 "foreach" 之前的所有客户作为数组
  2. 放入变量中
  3. 之后,您可以从数组而不是存储库中选择您的客户
  4. 创建一个 $toUpdate[] 数组,在其中放置所有 $customer 对象
  5. 最后,在 foreach 之外,您可以批量保存所有客户。

在这种情况下,foreach 中的每次迭代都有 2 个数据库请求。这相当于在一分钟内或大约有 20'000 个请求。

这是一个伪代码的想法:

$allCustomers = $this->_customerRepository()->getAll();
$bulkSave[];

foreach($customersListData as $customerIndex => $singleCustomerData)
{
    $myCustomer = $allCustomers->find($singleCustomerData['id']);
    $bulkSave[] = $myCustomer;
}

$this->_customerRepository()->save($bulkSave);

在构造函数中使用波纹管 class

\Magento\Framework\App\Action\Context $context,
    \Magento\Framework\View\Result\PageFactory $resultPageFactory,
    \Magento\Customer\Api\CustomerRepositoryInterface $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.') );
}

其他更快的选择

您应该在 magento 之外以编程方式使用 php 并与之建立数据库连接。获取数据并更新 magento 属性。这将更快、更容易地更新属性。