如何更快更有效地更新客户数据
How to update customer data faster and more efficiently
我正在编写一个脚本来为 10,000 个客户的自定义属性添加值。我有两个问题。
当我们更新产品的自定义属性值时,我们可以使用:
$resource = $product->getResource();
$product->setData($attribute, $value);
$resource->saveAttribute($product,$attribute);
这是非常快的。但是对于客户来说,它没有 getResource() 方法。我知道的唯一方法是: $this->_customerRepository->save($customer);这是非常非常慢的。那么我怎样才能更快地更新客户的价值呢?
当我批量更新这些值时,我编写了如下脚本,在前数百个客户数据更新时运行没问题,但随后抛出异常:
(/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;
}
}
}
- 将 "foreach" 之前的所有客户作为数组
放入变量中
- 之后,您可以从数组而不是存储库中选择您的客户
- 创建一个 $toUpdate[] 数组,在其中放置所有 $customer 对象
- 最后,在 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 属性。这将更快、更容易地更新属性。
我正在编写一个脚本来为 10,000 个客户的自定义属性添加值。我有两个问题。
当我们更新产品的自定义属性值时,我们可以使用:
$resource = $product->getResource(); $product->setData($attribute, $value); $resource->saveAttribute($product,$attribute);
这是非常快的。但是对于客户来说,它没有 getResource() 方法。我知道的唯一方法是: $this->_customerRepository->save($customer);这是非常非常慢的。那么我怎样才能更快地更新客户的价值呢?
当我批量更新这些值时,我编写了如下脚本,在前数百个客户数据更新时运行没问题,但随后抛出异常:
(/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; } } }
- 将 "foreach" 之前的所有客户作为数组 放入变量中
- 之后,您可以从数组而不是存储库中选择您的客户
- 创建一个 $toUpdate[] 数组,在其中放置所有 $customer 对象
- 最后,在 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 属性。这将更快、更容易地更新属性。