Skip to main content
Blog General

Magento 2: Import a category with its subcategories programmatically

Vijayashanthi M
July 11, 2019 |

Categories are essential for creating an efficient catalog and customer navigation so that users can easily find the products they want on your website.

Each product should be assigned to at least one category. Categories are a helpful way to sort and arrange your products. The diagram below represents the structure of the category.

Magento 2 categories with subcategories

The Magento 2 Import/Export function is one of the best resolutions for all stores to simplify numerous tasks in the manual back-end. These features become more essential and useful for Magento merchants.

Migrate To Magento 2

Does Default Magento 2 Open Source Support Import Categories?

The answer is definitely, no. In default Magento 2, the admin creates categories one by one, complete with the related data in each category. In the case of migrating to Magento 2, or when updating or moving to a new website, manually creating categories would be such a time-consuming work that not every business would tolerate it.

The below script helps you to import each category with its subcategories simultaneously without the compulsory need of the parent category ID. Instead of that, we can use the parent category name.

Create a custom module as shown in the file structure below.

Note: Please take a backup of your data and check with your technical developer before running the code.

Magento 2 categories with subcategories

Step 1: Create 

app/code/DCKAP/CategoryImport/view/frontend/layout/categoryimport_index_index.xml

<?xml version="1.0"?>
<page layout="2columns-left" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="navigation.sections" remove="true" />
<referenceContainer name="content">
<block class="Magento\Framework\View\Element\Template" name="catgoryimport.import" template="DCKAP_CategoryImport::categoryimport.phtml"/>
</referenceContainer>
</body>
</page>

Step 2: Create a form to import a CSV.

app/code/DCKAP/CategoryImport/view/frontend/templates/categoryimport.phtml

<div class="import-category">
<div class="header">
<h4>CSV File:</h4>
</div>
<form class="import-category-form" action="categoryimport" method="post" enctype="multipart/form-data">
<input type="file" required class="required-entry" name="file_upload" />
<button type="submit">Import</button>
</form>
</div>

CSV File:

Step 3: Create a controller to read and import the CSV.

app/code/DCKAP/CategoryImport/Controller/Index/Index.php

<?php
namespace DCKAP\CategoryImport\Controller\Index;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;


class Index extends \Magento\Framework\App\Action\Action
{
protected $_pageFactory;
protected $_categoryFactory;
protected $_category;
protected $_repository;
protected $csv;

public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $pageFactory,
\Magento\Catalog\Model\CategoryFactory $categoryFactory,
\Magento\Catalog\Model\Category $category,
\Magento\Framework\File\Csv $csv,
\Magento\Catalog\Api\CategoryRepositoryInterface $repository

)
{
$this->_pageFactory = $pageFactory;
$this->_categoryFactory = $categoryFactory;
$this->_category = $category;
$this->_repository = $repository;
$this->csv = $csv;
return parent::__construct($context);
}

public function execute()
{
$post = $this->getRequest()->getFiles();
if($post){
if(isset($post['file_upload']['tmp_name'])) {
$arrResult = $this->csv->getData($post['file_upload']['tmp_name']);
foreach ($arrResult as $key => $value) {
if ($key > 0){ // to skip the 1st row i.e title
$parentid =2;
if(is_string($value[1])){
$categoryTitle = $value[1];// Category Name
$collection = $this->_categoryFactory->create()->getCollection()->addFieldToFilter('name', ['in' => $categoryTitle]);

if ($collection->getSize()) {
$parentid = $collection->getFirstItem()->getId();
}
}else if(is_int(($value[1])))
$parentid = $value[1];
//echo $parentid."<br>";//For reference
$data = [
'data' => [
"parent_id" => $parentid,
'name' => $value[2],
"is_active" => true,
"position" => 10,
"include_in_menu" => true,
]
];
$checkCategory = $this->_categoryFactory->create()->getCollection()->addFieldToFilter('name', ['in' => $value[2]])->addFieldToFilter('parent_id', ['in' => $parentid]);
if(!$checkCategory->getData()){
$category = $this->_categoryFactory->create($data);
$result = $this->_repository->save($category);
}
}
$this->messageManager->addSuccessMessage('Category Imported Successfully');
}
}
}
$this->_view->loadLayout();
$this->_view->renderLayout();
}
}

Run this module:

http://localhost/magento/categoryimport/

Magento 2 categories with subcategories

The CSV format must be as shown below.

Click here to get a sample CSV.

In this CSV, your header will be what you want and the first column should be a serial number. The second column must be either a parent/root category ID or name, and the third column must be the name of the category.

************************ Import CSV File ************************

Sample CSV Format

S.No Parent Category ID/Name Category
1 2 Mobile
2 Mobile Samsung
3 Mobile Oppo
4 Mobile Vivo
5 Samsung Samsung J Pro
6 Samsung Samsung a 10
7 Oppo Oppo Youth
8 Oppo Oppo k1
9 Vivo Vivo v5 plus
10 Vivo Vivo v9

And finally, you can now simultaneously import each category with its subcategories. If you found this blog helpful, then please do let us know if you have any queries.

Vijayashanthi M

Vijayashanthi M is a passionate coder with an experience of 2.5 years in PHP, Yii 2, and Magento 2. She is always on the lookout for interesting things on the internet, and is an avid learner of new technologies. Her hobbies include dancing and listening to music.

More posts by Vijayashanthi M