4

I want to update product information for "All Store Views" but it seems that when I try to update a product, Magento ignores setStoreId(0). Instead the product information will be saved to store view 1.

For reference I have 4 store views: 1, 2, 3, 4 + store view 0 (admin).

enter image description here

My code:

$collection = $this->filter->getCollection($this->collectionFactory->create());

foreach ($collection->getAllIds() AS $productId)
{
    $product = $this->productRepository->getById($productId);

    $product->setStoreId(0);
    $product->setSpecialPrice(111);

    $this->productRepository->save($product);
}
2

If you only need to change a single product attribute, the product model has an addAttributeUpdate() method that takes store_id as a parameter:

$store_id = 0; // or 1,2,3,... ?
$attribute_code = 'name';
$value = 'Storeview Specific Name';

$product->addAttributeUpdate($attribute_code, $value, $store_id);

Looking at the method in ./vendor/magento/module-catalog/Model/Product.php - it automatically does the "save the current store code and switch back after the update" thing that the accepted answer does,

## ./vendor/magento/module-catalog/Model/Product.php

/**
 * Save current attribute with code $code and assign new value
 *
 * @param string $code  Attribute code
 * @param mixed  $value New attribute value
 * @param int    $store Store ID
 * @return void
 */
public function addAttributeUpdate($code, $value, $store)
{
    $oldValue = $this->getData($code);
    $oldStore = $this->getStoreId();

    $this->setData($code, $value);
    $this->setStoreId($store);
    $this->getResource()->saveAttribute($this, $code);

    $this->setData($code, $oldValue);
    $this->setStoreId($oldStore);
}
  • You answer helped me with a task I am working on. Thanks – diazwatson Jul 31 '18 at 13:26
7

I've noticed the same thing - Magento 2 ignores this:

$product->setStoreId(0);

So what we've done thats seems to allow us to achieve what you are trying to do is to use the \Magento\Store\Model\StoreManagerInterface instead.

In your constructor

public function __construct(
    \Magento\Store\Model\StoreManagerInterface $storeManager
) {
    $this->_storeManager = $storeManager;
} 

Then in your code before you try to update the products you can do:

$this->_storeManager->setCurrentStore(0);

Tip: I've started doing this though, to make sue that the appropriate store gets put back when I'm done:

$originalStoreId = $this->_storeManager->getStore()->getId();
$this->_storeManager->setCurrentStore(0);
// Do other things...
$this->_storeManager->setCurrentStore($originalStoreId);
  • If you have some values in store_id 1then it won't be updated with this method. BUT you can do foreach on store_ids (0,1,etc) and call save() from \Magento\Catalog\Api\ProductRepositoryInterface – Fred Orosko Dias Sep 24 '18 at 21:42
1

@Silas Palmer solution seems a better approach to me to solve your issue, but if you still have issues setting the default store id, you set the store id using an observer on catalog_product_save_before.

1.Creates the events.xml (I am placing mine in frontend)

<!-- /magento/app/code/VendorName/ModuleName/etc/frontend/events.xml -->
<?xml version="1.0" encoding="UTF-8"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
        <event name="catalog_product_save_before">
            <observer name="your_observer_name" instance="Vendor\YouModule\Observer\YourObserverName"/>
        </event>
    </config>

2.Set the store id using the observer

<?php
// magento/app/code/VendorName/ModuleName/Observer/YourObserverName.php
namespace VendorName\ModuleName\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Store\Model\Store;

class YourObserverName implements ObserverInterface
{

    /**
     * @param Observer $observer
     * @return void
     */
    public function execute(Observer $observer)
    {
        $product = $observer->getData('product');
        $product->setData('store_id', Store::DEFAULT_STORE_ID);
    }
}
0

You can use \Magento\Catalog\Model\ResourceModel\Product\Action like this:

public function __construct(
    \Magento\Catalog\Model\ResourceModel\Product\Action $productAction
) {
    $this->productAction = $productAction;
} 

And then quickly update atributes:

$this->productAction->updateAttributes(
    [$row->getProductId()], //array with product id's
    [
        $row->getAttributeCode() => $row->getAttributeValue(),
        $row->getOtherAttributeCode() => $row->getOtherAttributeValue()
    ],
    $storeId
);

This is especially good (fast) for changing attributes to many products at once.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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