11

How to set a product's custom attribute on save? I have used the event/observer way but nothing works.

Arnaud
  • 320
  • 4
  • 11
Jay Kapoor
  • 603
  • 2
  • 12
  • 30

7 Answers7

25

Official method should work, but Not

The official method setCustomAttribute($attributeCode, $attributeValue) below should work but NOT because the official bug https://github.com/magento/magento2/issues/4703.

The bug doesn't fix yet in version 2.2.3.

$product = $this->productRepository->getById($productId);
$product->setCustomAttribute($attributeCode, $attributeValue);
$this->productRepository->save($product);

Temporary method

After many debug and tries, I found the method $product->setData($attributeCode, $attributeValue) below could set custom attribute successfully, it is a temporary method.

Hope it could help you. Any better way is welcome to post :)

private $productRepository;

public function __construct( \Magento\Catalog\Api\ProductRepositoryInterface $productRepository ) { $this->productRepository = $productRepository; }

public function updateProductAttribute($productId) { $attributeCode = "Attribute_code"; $attributeValue = "Attribute Value Here"; $product = $this->productRepository->getById($productId); //$product->setCustomAttribute($attributeCode, $attributeValue); $product->setData($attributeCode, $attributeValue); $this->productRepository->save($product); }

Msquare
  • 9,063
  • 7
  • 25
  • 63
Key Shang
  • 3,415
  • 32
  • 58
  • This does not work for me using Magento 2.3.0. The only way I was able to get it was $product->getResource()->saveAttribute($product, $attributeValue); Very frustrating lol – quickshiftin Sep 12 '19 at 14:26
2

Rather using the setcustomattribute function you can just use this: Suppose your attribute code is inbound.

$product = $this->productRepository->getById($productId);
$product->setInbound($attributeValue);
$this->productRepository->save($product);
nihal malik
  • 491
  • 4
  • 12
2

The most upvoted answer didn't work for me on Magento 2.3.5 while creating a new product programatically.

Most probably because it depends on the type of custom attribute. If it's a dropdown or swatch, then you need to set the option ID, not the value.

So this is the method I ended up using (for the color attribute):

$product = $objectManager->create('Magento\Catalog\Model\Product');
$color = 'Black';
$product_resource = $product->getResource();
$color_attribute = $product_resource->getAttribute('color');
if ($color_attribute->usesSource()) {
    $color_option_id = $color_attribute->getSource()->getOptionId($color);
    if ($color_option_id != '') {
        $product->setData('color', $color_option_id);
    }
}       
... // set other attributes 
$product->save();
Lez
  • 2,907
  • 2
  • 23
  • 51
1

I would use event observer catalog_product_save_before to avoid loading and saving product separately extra time.

/** @var \Magento\Catalog\Model\Product $product */
$product = $observer->getData('product');
$product->setData('my_attribute', 'Some value');

Or plugin \Magento\Catalog\Model\ResourceModel\Product::beforeSave, because indexers already declare plugins on this method (for example, \Magento\CatalogRule\Plugin\Indexer\Product\Save\ApplyRules::afterSave);

Roman Kabanov
  • 796
  • 3
  • 10
1

For Magento 2.3.2
"Save" method of calss "Magento\Catalog\Api\ProductRepositoryInterface" not worked for me. Gives "Unique constraint violation found error". enter image description here

Method "updateAttributes" of class "Magento\Catalog\Model\ResourceModel\Product\Action" worked fine for me.

Pandurang Babar
  • 946
  • 6
  • 25
1
    <?php
namespace vendor\module\Observer;

class ProductSaveAfter implements \Magento\Framework\Event\ObserverInterface
{
    public function __construct(
        \Magento\Backend\Model\Auth\Session $authSession,
        \Magento\Catalog\Model\ProductFactory $productFactory
    ) {
        $this->authSession = $authSession;
        $this->productFactroy = $productFactory;
    }
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $user = $this->authSession->getUser()->getUsername();
        $productId = (int) $observer->getProduct()->getId();
        $product = $this->productFactroy->create()->load($productId);
        $product->addAttributeUpdate("updated_by", $user, 0);//attribute,value,storeid
    }
}
0
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // instance of object manager
            $product = $objectManager->create('\Magento\Catalog\Model\Product');

            $prod = $product->loadByAttribute('sku', $sku);
$prod->setCustomattribute($value); // name of your custom attribute
$prod->save();
Ashar Riaz
  • 1,035
  • 1
  • 14
  • 34
  • 1
    got this error SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction, query was: INSERT INTO catalog_product_entity_int (entity_id,attribute_id,value,store_id) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE entity_id = VALUES(entity_id), attribute_id = VALUES(attribute_id), value = VALUES(value), store_id = VALUES(store_id) – Jay Kapoor Sep 06 '17 at 11:28
  • i used the catalog_product_save_after event/observer method for this – Jay Kapoor Sep 06 '17 at 11:28
  • please add code here – Ashar Riaz Sep 06 '17 at 11:34
  • check link

    https://magento.stackexchange.com/questions/192201/magento-2-set-product-attribute-dynamically

    – Jay Kapoor Sep 06 '17 at 11:40
  • i posted a new question – Jay Kapoor Sep 06 '17 at 11:40