Como: Actualizar atributos de producto en Magento 2


Una vez tuve que actualizar un solo atributo en miles de productos a partir de una importación de datos. Mi primer instinto fue cargar cada producto con el repository, asignar el valor y guardarlo, y funcionó… pero era dolorosamente lento. Cargar y guardar un producto completo solo para cambiar un atributo es mucho trabajo desperdiciado. Existe una herramienta mucho mejor para esto.

La forma lenta (bien para un producto)

Si solo necesitas tocar un producto, el repository está perfectamente bien y es la opción más legible:

php
<?php
$product = $this->productRepository->get('sku-123');
$product->setData('my_attribute', 'new value');
$this->productRepository->save($product);

La forma rápida (para muchos productos)

Cuando necesitas actualizar el mismo atributo en muchos productos, usa Magento\Catalog\Model\Product\Action. Escribe directamente en las tablas del atributo sin cargar el modelo completo del producto, así que es muchísimo más rápido.

php
<?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  ej. ['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);
    }
}

Y para llamarlo:

php
$this->attributeUpdater->update([12, 34, 56], ['my_attribute' => 'new value']);
Nota: updateAttributes() asigna el valor para el scope de tienda indicado. Pasa Store::DEFAULT_STORE_ID (0) para actualizar el valor por defecto/global, o un store id específico para sobreescribirlo por store view.
Elijas la forma que elijas, recuerda que cambiar valores que afectan la tienda (precio, visibilidad, estado) programará un reindex. En un catálogo grande ejecuta tus indexers después para que los cambios aparezcan.

Espero que esto ayude.

Si tienes alguna pregunta o conoces una mejor manera de lograr esto, siéntete libre de compartir en los comentarios a continuación.