4

I have created simple product using following code.almost its working fine, but I'm not able assign product to websites.

Actually I have created two websites. I want to assign product to particular website or both websites. here

$this->product->setWebsiteIds(1);   $this->product->setWebsiteIds(array(1));

both lines not working.

In Magento\Catalog\Api\ProductRepositoryInterface there is no information websites (I mean there is no constants,setters,getters).

Anyone have idea?

namespace Kensium\Commands\Console;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
use Magento\Framework\App\State;
use Magento\Framework\App\ObjectManager\ConfigLoader;

/**
 * Command creates simple product by given data 
 */
class CreateSimpleProduct extends Command
{
    protected $_productRepository;
    protected $product;
    protected $registry;
    protected $state;
    protected $configLoader;
    protected $objectManager;
    const SIMPLE_PRODUCT_INFO = "simpleproductinfo";
    public function __construct(
         \Magento\Catalog\Api\ProductRepositoryInterface $_productRepository,
                 \Magento\Catalog\Api\Data\ProductInterface $product,
                 \Magento\Framework\Registry $registry,                 
                 State $state,
                 ConfigLoader $loader,
        \Magento\Framework\ObjectManagerInterface $objectManager
    )
    {
    $this->_productRepository =$_productRepository;
    $this->product=$product;
        $this->registry = $registry;       
        $this->state = $state;
    $this->configLoader = $loader;
        $this->objectManager = $objectManager;      
        parent::__construct();
    }

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('kensium:create_product')
            ->setDescription('creates simple product')->setDefinition([
            new InputArgument(self::SIMPLE_PRODUCT_INFO, InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'Simple Product Info')
        ]);

        parent::configure();
    }


    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {

    if (!$input->getArgument(self::SIMPLE_PRODUCT_INFO))
        {
            throw new \InvalidArgumentException('Missing Argument ' . self::SIMPLE_PRODUCT_INFO);
        }
        $this->registry->register('isSecureArea', true);
        $this->state->setAreaCode('adminhtml');
        $this->objectManager->configure($this->configLoader->load('adminhtml'));
        $simples=$input->getArgument(self::SIMPLE_PRODUCT_INFO);
        foreach($simples as $simple)
    {
           $arr=explode(":",$simple);
           $data['name']=$arr[0];
           $data['sku']=$arr[1];
           $data['price']=$arr[2];
       $this->product->setName($data['name']);
           $this->product->setSku($data['sku']);           
           $this->product->setPrice($data['price']);
           $this->product->setTypeId("simple");
           $this->product->setAttributeSetId(4);
           $this->product->setWebsiteIds(1); //   $this->product->setWebsiteIds(array(1)); 
       $this->_productRepository->save($this->product); 
           $output->writeln('<info>created simple product</info>');
    }


    }


}
3
  • 1
    it should work with setWebsiteIds(array(1)). I have no idea why it doesn't work for you but you can try with $this->product->save() instead of $this->_productRepository->save($this->product).
    – Marius
    May 8 '15 at 8:13
  • working fine with $this->product->save() & setWebsiteIds(array(1))
    – sivakumar
    May 8 '15 at 9:02
  • but no idea when to use productRepository.any way thanks Marius.
    – sivakumar
    May 8 '15 at 9:03
1

Based on the comments...

it should work with setWebsiteIds(array(1)). I have no idea why it doesn't work for you but you can try with $this->product->save() instead of $this->_productRepository->save($this->product)

3
  • It's work currently. But in future this code will be broken, because the product interface do not have setWebsiteIds method
    – KAndy
    Dec 14 '15 at 7:57
  • @KAndy. It worked when I answered this question. Sometimes I cannot predict the future. This is one of the cases.
    – Marius
    Dec 14 '15 at 8:01
  • Using $this->product->save over the repository means that you cannot assign a configurable product to a website programmatically.
    – p3mbo
    Mar 2 '16 at 19:10
1

I encountered the same issue and found that adding the website after the product has been saved to be the solution.

I used instances of the Magento\Catalog\Api\Data\ProductWebsiteLinkInterface and Magento\Catalog\Api\ProductWebsiteLinkRepositoryInterface repository with code similar to the below:

...

$mageProduct = $this->productRepository->save($mageProduct, true);

// Instance of ProductWebsiteLinkInterface
$siteLink = $this->productWebsiteLink;
$siteLink->setSku($mageProduct->getSku());
$siteLink->setWebsiteId(1);

// Instance of ProductWebsiteLinkRepositoryInterface
$websiteLinkRepo = $this->productWebsiteLinkRepository;
$websiteLinkRepo->save($siteLink);
0

I experienced some confusing application behavior when trying to add simple and configurable products to specific websites/stores in Magento 2.2.

My preferred solution:

/**
 * This version sets one of the stores the product is assigned to 
 * as the "current store"
 * and assigns the product to other websites via setWebsiteIds[...].
 * Disadvantage: There is no store with all products inside.
 * The product is assigned to websites 2, 4 and 5 in this example: 
 */

$websiteIds = [2, 4, 5]; // this is obviously dynamically set by an external system
$this->storeManager->setCurrentStoreId($websiteIds[0]);

$newProduct = $this->productInterfaceFactory->create();

$newProduct->setWebsiteIds($websiteIds);

// ... add other attributes
$savedProduct = $this->productRepository->save($newProduct);

If changing default stores is not preferred, then it is also a possibility to use a hidden admin store:

/**
 * This version sets a hidden admin store as the "current store"
 * and assigns the product to other websites via setWebsiteIds[...].
 * Disadvantage: Every product is assigned to the hidden admin store.
 * Advantage: Every product can be asssigned to and unassigned from
 * any (other) store programmatically.
 * The product is assigned to websites 2, 4 and 5 in this example: 
 */

$this->storeManager->setCurrentStoreId(5);

$newProduct = $this->productInterfaceFactory->create();

$newProduct->setWebsiteIds([2,4]);

// ... add other attributes
$savedProduct = $this->productRepository->save($newProduct);

If a product is always needed in all stores, this solution might be fine:

/**
 * If the current store is set to 0, each product is assigned to every
 * website. I would not know how to unassign a specific store: Stores 
 * can NOT be unassigned via $newProduct->setWebsiteIds([]);.
 */

$this->storeManager->setCurrentStoreId(0);

$newProduct = $this->productInterfaceFactory->create();
$newProduct->setStoreId(1); // This does not seem to have any impact.
$newProduct->setWebsiteIds([2]); // This does not seem to have any impact.

// ... add other attributes
$savedProduct = $this->productRepository->save($newProduct);

Not setting the current store seems to result in a slightly random scenario:

/**
 * Here, the current store of the store manager is not set.
 * This version does work, but in addition to store id 2, each product
 * has a second store assigned in my case. 
 * That second store seems to be quite random.
 */

$newProduct = $this->productInterfaceFactory->create();
$newProduct->setWebsiteIds([2]);

// ... add other attributes
$savedProduct = $this->productRepository->save($newProduct);

As a result, I keep these findings:

  • It seems to be necessary to set the current store via the store manager before creating the product. Not setting it makes the results a bit random.
  • Setting the current store to 0 assigns every product to all stores, but makes it hard to unassign them.
  • If a product is created with the current store set, it can be assigned to a choice of websites.
  • It seems to be not necessary to save the product twice; the websites can be chosen during the initial product creation.

I think, my research session was a bit funny; other people might know how to find that kind of information easier by looking through documentation or investigating code - but I did both, and even asked my colleagues, and nobody seemed to know. Hope, it helps anyone.

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.