How to set a product's custom attribute on save? I have used the event/observer way but nothing works.
7 Answers
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);
}
-
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
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();
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);
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);
<?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
}
}
$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();
-
1got 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 UPDATEentity_id
= VALUES(entity_id
),attribute_id
= VALUES(attribute_id
),value
= VALUES(value
),store_id
= VALUES(store_id
) Commented Sep 6, 2017 at 11:28 -
i used the
catalog_product_save_after
event/observer method for this Commented Sep 6, 2017 at 11:28 -
-
-