Quick script to batch create Magento categories

A site we administer with a reasonable amount of SKUs (far in excess of 100,000), needed some quick category manipulation for a series of new data to be dropped in. The new information had a desired category tree that had to be built up quick, but with over 600 categories to be created, human effort wouldn’t be suitable.

So, using the Magento category ID export script to help manipulate the CSV – we were able to quickly make a script to batch create our categories.

First off, create your CSV with 2 columns, the parent ID for the category and the category name – you could easily add more columns for extra options, but it wasn’t necessary for us.

The CSV file should be something like this:

3,subcat
4,subcat2
6,subcat3

Then it should be saved in ./var/import/importCats.csv

Then save the following in ./quickCatCreate.php

<?php

        define('MAGENTO', realpath(dirname(__FILE__)));
        require_once MAGENTO . '/app/Mage.php';

        umask(0);
        Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
        $count = 0;

	$file = fopen('./var/import/importCats.csv', 'r');
	while (($line = fgetcsv($file)) !== FALSE) { $count++;
	  //$line is an array of the csv elements
	  
	  if (!empty($line[0]) && !empty($line[1])) { 
	  	
		  $data['general']['path'] = $line[0];
		  $data['general']['name'] = $line[1];
		  $data['general']['meta_title'] = "";
		  $data['general']['meta_description'] = "";
		  $data['general']['is_active'] = "";
		  $data['general']['url_key'] = "";
		  $data['general']['display_mode'] = "PRODUCTS";
		  $data['general']['is_anchor'] = 0;
	  
		  $data['category']['parent'] = $line[0]; // 3 top level
		  $storeId = 0;
		  
		  createCategory($data,$storeId);
		  sleep(0.5);
		  unset($data);
		}

	}  
	
  
  function createCategory($data,$storeId) {
  	
  	echo "Starting {$data['general']['name']} [{$data['category']['parent']}] ...";
  	     
      $category = Mage::getModel('catalog/category');
      $category->setStoreId($storeId);
      
      # Fix must be applied to run script
      #http://www.magentocommerce.com/boards/appserv/main.php/viewreply/157328/
  	
		  if (is_array($data)) {
		      $category->addData($data['general']);
		      
		      if (!$category->getId()) {

		          $parentId = $data['category']['parent'];
		          if (!$parentId) {
		              if ($storeId) {
		                  $parentId = Mage::app()->getStore($storeId)->getRootCategoryId();
		              }
		              else {
		                  $parentId = Mage_Catalog_Model_Category::TREE_ROOT_ID;
		              }
		          }
		          $parentCategory = Mage::getModel('catalog/category')->load($parentId);
		          $category->setPath($parentCategory->getPath());

		      }
		      
					/**
					 * Check "Use Default Value" checkboxes values
					 */
					if ($useDefaults = $data['use_default']) {
					    foreach ($useDefaults as $attributeCode) {
					        $category->setData($attributeCode, null);
					    }
					}		      
		      
		      $category->setAttributeSetId($category->getDefaultAttributeSetId());
		
		      if (isset($data['category_products']) &&
		          !$category->getProductsReadonly()) {
		          $products = array();
		          parse_str($data['category_products'], $products);
		          $category->setPostedProducts($products);
		      }
		      		
		      try {
		          $category->save();
		          echo "Suceeded <br /> ";
		      }
		      catch (Exception $e){
		      		echo "Failed <br />";

		      }
		  }  	
  	
  }

Then it is just a matter of visiting the link in your browser to create the categories – customise to your hearts content, any further expansion should be very easy (such as product association etc.)

Uh oh – I’m getting errors after the first record!

Fatal error: Call to a member function getPath() on a non-object in appcodecoreMageCatalogModelResourceEavMysql4Category.php on line 385 

There is a small NB though, there is a bug with Magento’s original code that will cause a problem with the above script, a quick fix is outlined here. It is just a matter of commenting out 2 lines to force the variable to be re-set.

In ./app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category.php line #110

protected function _getTree()
    {
        //if (!$this->_tree) {
            $this->_tree = Mage::getResourceModel('catalog/category_tree')
                ->load();
        //}
        return $this->_tree;
    } 
  • Mike

    Ben,

    I’m having the same problem and I don’t know how to fix it. The old database starts at 39 and if I use Santosh’s Import the categories start at 3, thus all of the products are off.

    Now that I loaded your script its showing up in the database, but not in the back or frontend of Magento. How do I set the root category ID?

  • amit samsukha

    Hi All,
    I got following error after 1st category added

    Fatal error: Undefined class constant ‘Mage_Catalog_Model_Convert_Adapter_Product::ENTITY’ in C:\Program Files\EasyPHP5.2.10\www\magento\app\code\core\Mage\Core\Model\Config.php on line 1254

    this constant is defined in Product.php(Mage_Catalog_Model_Convert_Adapter_Product)

    any idea about this .. ??

  • http://www.onlinemarineproducts.com Adam

    Brilliant. This is the best script i have used for magento. I had 215 categories which i thought i would have to do manually. Script worked first time.

    Cheers mate!

  • http://elygor.de Sebastian

    If I try to run the script it says: Successful and the categorie was created. But empty. No name, nothing. What’s wrong?

  • sunil

    I run this file using command but category not display in backed side..

  • Ben Giles

    Worked a treat for me, I used the instructions from here http://www.marblemultimedia.com/quickly-add-multiple-categories-magento

    Found them a bit more user friendly
    Thanks

  • Mihau

    can i use this script to import sub categories?

    e.g.

    Apparel
    -Shoes
    –Mens
    –Womens

    Electronics
    -Cameras
    –Accessories
    –Digital Cameras

  • http://www.gparts.co.uk Neil Spinney

    Hi Guys
    I have tried the script above but when I goto the page http://gparts.nstekhosting.com/s1/catimport.php
    it does nothing???
    I’m currenlty running Magento ver. 1.5.1.0
    Any ideas?

  • http://www.gparts.co.uk Neil Spinney

    Sorry I was being a total numpty as I was putting all of my categories in the same columns in excel!!

    :-0

  • http://www.sonassi.com Benjamin

    Yes, but you have to be creative to do it. Creating a category by setting the ID breaks the “children_count” functionality – so it has an adverse effect throughout the rest of the site.

    So creating a hierarchy requires some modification to either create categories in levels (create level 1′s, export IDs, map parents in CSV and create level 2′s – and repeat).

    Alternatively, a 1-run solution won’t facilitate what you want out of the box – but with some minor modifications, it can do. We use a slight variant of this script on a regular basis to create category trees from a source CSV.

  • manish

    It works without any error ….Thanks for the script

  • http://www.sonassi.com Benjamin

    Hi Stephen,

    When creating categories and setting the ID, leave the path blank (it *should* be automatically set).

    Afterwards, you’ll need to run this code http://www.sonassi.com/knowledge-base/magento-knowledge-base/magento-category-children-count-fix/

  • http://www.sonassi.com Benjamin

    To follow up on this, here is some SQL to fix the children_count

    http://www.sonassi.com/knowledge-base/magento-knowledge-base/magento-category-children-count-fix/

  • Pingback: Magento batch update category quick script | Magento design, development and suport :: sonassi

  • http://scooterdoctor.com premie

    Thank you!! It works as described! I couldn’t get the Santosh version working on 1.6, so this was a great find!

    Magento 1.6, works!

  • http://www.inturias.com Jorge A. Inturias

    Hi, first off, Thank you was a great work.

    But I have a problem, how could I modify your script in order to add “accent (á)” and “coma (,)” for the Spanish language?? because in english work GREAT!

  • http://www.inturias.com Jorge A. Inturias

    for me work this:

    I added this line:
    setlocale(LC_ALL, ‘en_US.UTF-8′);
    And I ensure that my .csv was in UTF-8

    that’s all.

    Regards

  • http://jarco.be jarco

    Hey,
    If you want them all to be active you can also set this:

    $data['general']['is_active'] = "";

  • http://jarco.be jarco

    That was an error. i mean to set it to :
    $data['general']['is_active'] = "1";

  • Pingback: Magento for noobies, dicas de artigos | Bruno PorKaria #mobiletalk

  • Grisales

    I am having a hard time with this one here…

    1st error: Fatal error: Maximum execution time of 30 seconds exceeded in
    /home/atcomco/public_html/emshop/app/Mage.php on line 703

    i fix this in the php.ini and goes trough but the new error states about issues with the PDO

    2nd error: Fatal error: Uncaught exception ‘Zend_Db_Adapter_Exception’ with message ‘The PDO extension is required for this adapter but the extension is not loaded’ 

    Inserted in the php.ini the following:

    extension=pdo.so
    extension=pdo_mysql.sobut end up in a server side error.the log shows this:[14-Jun-2012 23:37:47] PHP Fatal error:  Uncaught exception ‘PDOException’ with message ‘SQLSTATE[42S02]: Base table or view not found: 1146 Table ‘atcomco_emshop.core_file_storage’ doesn’t exist’ in /home/atcomco/public_html/emshop/lib/Zend/Db/Statement/Pdo.php:228Stack trace:#0 /home/atcomco/public_html/emshop/lib/Zend/Db/Statement/Pdo.php(228): PDOStatement->execute(Array)#1 /home/atcomco/public_html/emshop/lib/Zend/Db/Statement.php(300): Zend_Db_Statement_Pdo->_execute(Array)#2 /home/atcomco/public_html/emshop/lib/Zend/Db/Adapter/Abstract.php(479): Zend_Db_Statement->execute(Array)#3 /home/atcomco/public_html/emshop/lib/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract->query(‘SELECT `e`.* FR…’, Array)#4 /home/atcomco/public_html/emshop/lib/Varien/Db/Adapter/Pdo/Mysql.php(337): Zend_Db_Adapter_Pdo_Abstract->query(‘SELECT `e`.* FR…’, Array)#5 /home/atcomco/public_html/emshop/lib/Zend/Db/Adapter/Abstract.php(753): Varien_Db_Adapter_Pdo_Mysql->query(Object(Varien_Db_Select), Array)#6 /home/atcomco/public_html/emshop/app/co in /home/atcomco/public_html/emshop/lib/Zend/Db/Statement/Pdo.php on line 234

  • sonassi

    Change your hosting to a proper Magento web host. Try http://www.sonassihosting.com

  • http://twitter.com/hd_ng Tom Harding

    Awesome script guys, that’s saved me having to manually input 750 categories. :-)

  • Amigo

    Hi! You know, once I had a lots of problems with my products after import.Luckily, I had made my data backup before it and this Magento extension helped me much http://www.magentocommerce.com/magento-connect/file2cart-magento-product-import-9633.html