Import category structure with products using DataFlow

Last modified by FerdiUSA on Fri, June 25, 2010 09:41
Source|Old Revisions  

This is an old revision of the document!


Abstract

This article will outline functionality of importing new categories and/or associating new/existing products with categories.

  • The categories will be imported from field named “categories”.
  • Categories should be in format “Category/Subcat1/Subcat2”.
  • Category names can have whitespaces around, they will be trimmed.
  • It is possible to provide multiple categories for same product line by separating them with comma.
  • The lines with “categories” must have “store” field with correct values.
  • UPDATED: Category names are not case-sensitive unique.

An example of import file with required fields for existing products:

"store","sku","categories"
"default","FOO","Apparel/Shoes,Clearance"
"default","BAR","Electronics"

Using Pre-Patched files

For easy fix, download the appropriate file

and unzip into app/code/local/Mage/Catalog/Model/Convert/Adapter/

Patching

You can also patch the file yourself if using the patched files is not an option.

Preparation for integration in extension

You will need to follow this article: customize_part_of_configuration to overload class contained in this file: app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php

It is OK to use existing local custom extension if available.

New functionality

In your custom overloaded class add these property and method:

  1.     protected $_categoryCache = array();
  2.     protected function _addCategories($categories, $store)
  3.     {
  4.         $rootId = $store->getRootCategoryId();
  5.         if (!$rootId) {
  6.             return array();
  7.         }
  8.         $rootPath = '1/'.$rootId;
  9.         if (empty($this->_categoryCache[$store->getId()])) {
  10.             $collection = Mage::getModel('catalog/category')->getCollection()
  11.                 ->setStore($store)
  12.                 ->addAttributeToSelect('name');
  13.             $collection->getSelect()->where("path like '".$rootPath."/%'");
  14.  
  15.             foreach ($collection as $cat) {
  16.                 $pathArr = explode('/', $cat->getPath());
  17.                 $namePath = '';
  18.                 for ($i=2, $l=sizeof($pathArr); $i<$l; $i++) {
  19.                     $name = $collection->getItemById($pathArr[$i])->getName();
  20.                     $namePath .= (empty($namePath) ? '' : '/').trim($name);
  21.                 }
  22.                 $cat->setNamePath($namePath);
  23.             }
  24.            
  25.             $cache = array();
  26.             foreach ($collection as $cat) {
  27.                 $cache[strtolower($cat->getNamePath())] = $cat;
  28.                 $cat->unsNamePath();
  29.             }
  30.             $this->_categoryCache[$store->getId()] = $cache;
  31.         }
  32.         $cache =& $this->_categoryCache[$store->getId()];
  33.        
  34.         $catIds = array();
  35.         foreach (explode(',', $categories) as $categoryPathStr) {
  36.             $categoryPathStr = preg_replace('#s*/s*#', '/', trim($categoryPathStr));
  37.             if (!empty($cache[$categoryPathStr])) {
  38.                 $catIds[] = $cache[$categoryPathStr]->getId();
  39.                 continue;
  40.             }
  41.             $path = $rootPath;
  42.             $namePath = '';
  43.             foreach (explode('/', $categoryPathStr) as $catName) {
  44.                 $namePath .= (empty($namePath) ? '' : '/').strtolower($catName);
  45.                 if (empty($cache[$namePath])) {
  46.                     $cat = Mage::getModel('catalog/category')
  47.                         ->setStoreId($store->getId())
  48.                         ->setPath($path)
  49.                         ->setName($catName)
  50. // comment out the following line if new categories should stay inactive
  51.                         ->setIsActive(1)
  52.                         ->save();
  53.                     $cache[$namePath] = $cat;
  54.                 }
  55.                 $catId = $cache[$namePath]->getId();
  56.                 $path .= '/'.$catId;
  57.             }
  58.             if ($catId) {
  59.                 $catIds[] = $catId;
  60.             }
  61.         }
  62.         return join(',', $catIds);
  63.     }

Changing existing method

Copy the whole public function saveRow(array $importData) into custom class and make the following change:

  1. // right after this:
  2.         if (isset($importData['category_ids'])) {
  3.             $product->setCategoryIds($importData['category_ids']);
  4.         }
  5. // add this:
  6.         if (isset($importData['categories'])) {
  7. /* Modified By AngelX */
  8.             if (isset($importData['store'])) {
  9.                 $cat_store = $this->_stores[$importData['store']];
  10.             } else {
  11.                     $message = Mage::helper('catalog')->__('Skip import row, required field "store" for new products not defined', $field);
  12.                     Mage::throwException($message);
  13.             }
  14.                  
  15.             $categoryIds = $this->_addCategories($importData['categories'], $cat_store);
  16.             if ($categoryIds) {
  17.                 $product->setCategoryIds($categoryIds);
  18.             }
  19. /* End Modify */
  20.         }



 

Magento 2 GitHub Repository

Magento Job Board - Some sort of tag line goes here

Latest Posts| View all Jobs