Magento – CSV Import: How to import related products in Magento 2

csvimportmagento2related-products

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?

Best Answer

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>');
    }
}
Related Topic