HowTo: Update Product Attributes in Magento 2
On this page
I once had to update a single attribute on thousands of products from a data import. My first instinct was to load each product with the repository, set the value and save it, and it worked… but it was painfully slow. Loading and saving a full product just to change one attribute is a lot of wasted work. There is a much better tool for this.
The slow way (fine for one product)
If you only need to touch one product, the repository is perfectly fine and the most readable option:
<?php
$product = $this->productRepository->get('sku-123');
$product->setData('my_attribute', 'new value');
$this->productRepository->save($product);The fast way (for many products)
When you need to update the same attribute on a lot of products, use Magento\Catalog\Model\Product\Action. It writes
straight to the attribute tables without loading the whole product model, so it is dramatically faster.
<?php
/** app/code/Vendor/Module/Model/AttributeUpdater.php */
namespace Vendor\Module\Model;
use Magento\Catalog\Model\Product\Action;
use Magento\Store\Model\Store;
class AttributeUpdater
{
/**
* @var Action
*/
private $productAction;
/**
* @param Action $productAction
*/
public function __construct(Action $productAction)
{
$this->productAction = $productAction;
}
/**
* @param int[] $productIds
* @param array $attributes e.g. ['my_attribute' => 'new value']
* @param int $storeId
*/
public function update(array $productIds, array $attributes, $storeId = Store::DEFAULT_STORE_ID)
{
$this->productAction->updateAttributes($productIds, $attributes, $storeId);
}
}And calling it:
$this->attributeUpdater->update([12, 34, 56], ['my_attribute' => 'new value']);updateAttributes() sets the value for the given store scope. Pass Store::DEFAULT_STORE_ID (0) to update the default/global value, or a specific store id to override it per store view.Hope this helps.
If you have any question or know a better way to achieve this, feel free to share in the comments below.