11

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

7 Answers 7

26

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);
}
1
  • 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 Commented Sep 12, 2019 at 14:26
3

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();
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);
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);

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.

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();
5
  • 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
    Commented Sep 6, 2017 at 11:28
  • i used the catalog_product_save_after event/observer method for this
    – Jay Kapoor
    Commented Sep 6, 2017 at 11:28
  • please add code here
    – Ashar Riaz
    Commented Sep 6, 2017 at 11:34
  • check link magento.stackexchange.com/questions/192201/…
    – Jay Kapoor
    Commented Sep 6, 2017 at 11:40
  • i posted a new question
    – Jay Kapoor
    Commented Sep 6, 2017 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.