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

时间:2017-12-05 12:47:38

标签: php magento2

我正在编写一个脚本,为1万个客户的自定义属性添加值。我在这里有两个问题。

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

    $resource = $product->getResource();
    $product->setData($attribute, $value);
    $resource->saveAttribute($product,$attribute);
    
  2. 这非常快。但至于客户,它没有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;
          }
        }
      }
      

2 个答案:

答案 0 :(得分:0)

  1. 将“foreach”之前的所有客户变为数组变量
  2. 之后,您可以从阵列而不是存储库中选择您的客户
  3. 制作$ toUpdate []数组,放置所有$ customer对象
  4. 最后,在foreach之外,您可以批量保存所有客户。
  5. 在这种情况下,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);
    

答案 1 :(得分:0)

在构造函数中使用bellow类

\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.') );
}

另类更快的选择

你应该以编程方式使用php out side magento并与之建立数据库连接。获取数据并更新magento属性。这将更快,更容易更新属性。