9

How can I import related products via csv in Magento 2?

In my csv file I have a row with attribute related_skus with example data "11-111,22-222" for a product. But in admin Products->Catalog in this imported product the sidebar tab Related Products show no products although those products with skus exist in catalog.

Where can be the mistake?

6
  • Magento showed any errors? What's is your Import Behavior: Add/Update, Replace or Delete? Commented May 18, 2016 at 3:22
  • No errors, import was successfully completed. Import Behavior was "Add/Update".
    – Guest
    Commented May 18, 2016 at 7:16
  • You try to re-index your database? Commented May 18, 2016 at 7:24
  • Yes, I used the command php bin/magento indexer:reindex and flushed the cache. I used pipe "|" as Multiple value separator and the example data was "11-111|22-222". Perhaps Magento doesn't support another multiple value separator for related_skus attribute?
    – Guest
    Commented May 18, 2016 at 7:31
  • Have you been achieve to import your products now ?
    – Nolwennig
    Commented Feb 14, 2017 at 15:36

1 Answer 1

7

We've experienced the same issue, it seems import module has some kind of bug with related products

We've solved it by writing a new console command which expects a 2 columns (parent sku & children skus) related.csv file in var folder, with comma as csv separator, and pipe as children_skus separator

This are the files, if you want to try. You'd replace Sinapsis with your desired vendor name, and Sync with your desired module name

After installing the module, run bin/magento setup:upgrade & you'll see the new command if you check bin/magento list, which could be executed by running bin/magento sync:related

update

Since 2.2.* version, there are 2 changes required: an extra line before saving $product, to prevent issue reported here https://github.com/magento/magento2/issues/10687

$product->unsetData('media_gallery');

And changing admin to adminhtml in

$this->_appState->setAreaCode('adminhtml');

I think first change is innocuous for older versions, not the same for the second. So I have added only the first in below code

app / code / Sinapsis / Sync / etc / di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\Console\CommandList">
    <arguments>
        <argument name="commands" xsi:type="array">
            <item name="sync_related" xsi:type="object">Sinapsis\Sync\Console\Command\RelatedCommand</item>
        </argument>
    </arguments>
</type>

app / code / Sinapsis / Sync / etc / module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="module.xsd">
<module name="Sinapsis_Sync" setup_version="1.0.0">
</module>

app / code / Sinapsis / Sync / registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Sinapsis_Sync',
    __DIR__
);

app / code / Sinapsis / Sync / Console / Command / RelatedCommand.php

<?php
namespace Sinapsis\Sync\Console\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\App\State as AppState;
use Magento\Framework\App\Filesystem\DirectoryList;

class RelatedCommand extends Command
{
    const CSV_SEPARATOR = ',';
    const CHILDREN_SEPARATOR = '|';

    protected $_appState;
    protected $_objectManager;
    protected $_directorylist;

    public function __construct(
        DirectoryList $_directorylist,
        AppState $appState,
        ObjectManagerInterface $objectManager
    ) {
        $this->_appState = $appState;
        $this->_objectManager = $objectManager;
        $this->_directorylist = $_directorylist;
        parent::__construct();
    }

    protected function configure()
    {
        $this->setName('sync:related')
            ->setDescription('Synchronize catalog related products');
        parent::configure();
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('<info>Starting process...<info>');
        $output->writeln('');

        $this->_appState->setAreaCode('admin');
        $productRepository = $this->_objectManager->create('Magento\Catalog\Model\ProductRepository');
        $output->writeln('<info>Loading csv content...<info>');
        $output->writeln('');

        $filePath = $this->_directorylist->getPath('var') . DIRECTORY_SEPARATOR . 'related.csv';
        //@todo control Exception if file does not exist
        $parseData = array();
        if (($handle = fopen($filePath, "r")) !== FALSE) {
            while (($data = fgetcsv($handle, 0, self::CSV_SEPARATOR)) !== FALSE) {
                $parseData[] = $data;
            }
            fclose($handle);
        } else {
            $output->writeln('<info>Could not read .csv file<info>');
            return;
        }
        $headers = array_shift($parseData); // remove headers

        foreach ($parseData as $row){

            $skuParent = trim($row[0]);
            $skuChildren = trim($row[1]);
            $output->writeln('<info>Loading parent product ' . $skuParent . ' ... <info>');

            try {
                $product = $productRepository->get($skuParent);
            } catch (\Magento\Framework\Exception\NoSuchEntityException $e){
                $output->writeln('<info>Could not load!<info>');
                continue;
            }

            $links = $product->getProductLinks();
            $children = explode(self::CHILDREN_SEPARATOR, $skuChildren);

            $i = 1;
            foreach ($children as $skuChild){

                $output->writeln('<info>Loading related product ' . $skuChild . ' ... <info>');

                try {
                    $child = $productRepository->get($skuChild);
                } catch (\Magento\Framework\Exception\NoSuchEntityException $e){
                    $output->writeln('<info>Could not load!<info>');
                    continue;
                }

                $productLink = $this->_objectManager->create('Magento\Catalog\Api\Data\ProductLinkInterface')
                    ->setSku($skuParent)
                    ->setLinkedProductSku($skuChild)
                    ->setPosition($i)
                    ->setLinkType('related');
                $links[] = $productLink;
                $i++;
            }

            $product->setProductLinks($links);
            $product->unsetData('media_gallery');
            $productRepository->save($product);
            $output->writeln('<info>Relations saved for ' . $skuParent . '<info>');

        }
        $output->writeln('');
        $output->writeln('<info>Done<info>');
    }
}
3
  • is this code will work while creating new products but as far as i checked your code here you are adding related products to the existing parent sku. Commented Sep 25, 2019 at 14:17
  • If you have any idea while creating parent sku only can we add some related/upsell/crossel skus to that product. Please suggest me thanks in Advance. Commented Sep 25, 2019 at 14:18
  • This code worked for me thanks @Raul Sanchez Commented Sep 25, 2019 at 15:50

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.