Хорошая практика: как сохранить много объектов?
У меня есть вопрос относительно хорошей практики: как правильно сохранить много объектов?
Предположим, я изменил множество объектов в коллекции, скажем, в коллекции продуктов. Вот что я мог бы сделать:
...
foreach($productCollection as $product{
$this->productRepository->save($product);
}
...
Однако использование метода сохранить() в цикле не только плохая практика, но и подчеркивается PHP CS. Конечно, если коллекция содержит только 4 или 5 продуктов, это не изменит облик мира, но иногда это явно наиболее чем это.
Я знаю, что если я изменяю только атрибут, мне не нужно использовать репозиторий и я могу использовать встроенный компонент Magento для обновления атрибутов, однако иногда мне также нужно выполнить некоторую логику и действительно нужна сущность продукта.
Итак, у кого-нибудь есть хорошая практика, которой можно поделиться в этом контексте?
1 answers
Если вам нужно выполнить массовое обновление одного (или нескольких атрибутов) до одного и того же значения, вы можете использовать:
$this->_objectManager->get('Magento\Catalog\Model\Product\Action')
->updateAttributes($productIds, ['status' => $status], $storeId);
В этом примере мы обновляем все продукты, соответствующие идентификатору ($productIds - это массив идентификаторов продуктов), устанавливая их статус атрибут к значению $status, для магазина $ Хранитель.
Если вы хотите просто обновить один атрибут в коллекции продуктов, вы можете использовать (в своем случай):
...
foreach($productCollection as $product{
$product->addAttributeUpdate($attributeCode, $value, $store);
}
...
$ Код атрибута представляет имя атрибута, которое должно быть сохранено
$ ценность представляет значение, которое вы хотите установить для сущности
$ хранить представляет идентификатор магазина, это может быть $product->getstoreid()
Проблема с Добавить атрибут обновить() является ли это атрибутом обновления, но он не обновляет загруженную в данный момент модель продукта. Взгляните на реализацию в Magento\Catalog\Model\Product
:
/**
* Save current attribute with code $code and assign a new value
*
* @param string $code Attribute code
* @param mixed $value New attribute value
* @param int $store Store ID
* @return void
*/
public function addAttributeUpdate($code, $value, $store)
{
$oldValue = $this->getData($code);
$oldStore = $this->getStoreId();
$this->setData($code, $value);
$this->setStoreId($store);
$this->getResource()->saveAttribute($this, $code);
$this->setData($code, $oldValue);
$this->setStoreId($oldStore);
}
В этом случае лучше использовать что-то вроде, productResource
является Magento\Catalog\Model\ResourceModel\Product
:
...
foreach($productCollection as $product{
// its sugessted to inject resource as dependency than using deprecated getResource() method.
// check reference for more information.
// $product->getResource()->saveAttribute($product, $attributeCode);
$this->productResource->saveAttribute($product, $attributeCode);
}
...
Недостаток этого решения становится заметным, когда вы работаете над большие коллекции. Вот почему у нас есть итераторы который захватывает данные из базы данных, один за другим, и таким образом предотвращает истощение памяти.
...
$this->_dataObject = $this->_objectManager->get('Magento\Catalog\Model\Product');
$iterator = $this->_objectManager->get('Magento\Framework\Model\ResourceModel\Iterator')
$iterator->walk($productCollection->getSelect(), [[$this, 'walkCallback']]);
...
public function walkCallback($data)
{
$this->_dataObject->reset(); // clean up shared object
$this->_dataObject->setData($data['row']); // map data to product model
$this->_dataObject->setDescription('test');
$this->_dataObject->getResource()->saveAttribute($this->_dataObject, 'description'); // save only changed attribute instead of whole object
}
Это идеи, которые вы можете использовать для управления коллекциями.
Ссылка: https://github.com/magento/magento-coding-standard/pull/189