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 app\code\core\Mage\Catalog\Model\Resource\Eav\Mysql4\Category.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;
    }
This entry was posted in Knowledge Base, Magento and tagged , , , , , , , . Bookmark the permalink.

49 Responses to Quick script to batch create Magento categories

  1. Any tips if nothing is shown at all?

    I’ve put E_ALL errors at the top but still nothing. It does echo out the ‘running script’ line I put in there but that’s it.

    Reply


  2. Now got…

    ini_set(’error_reporting’, E_ALL);

    ini_set(’display_errors’, 1);

    echo “Running import”;

    …at the top. Still nothing displayed other than Running import.

    Import file is definitely readable.

    Reply


  3. Got a tiny bit further forward and now have an error message.

    Fatal error: Uncaught exception ‘Exception’ with message ‘Notice: Undefined variable: count in /var/www/vhosts/site/httpdocs/quickCatCreate.php on line 13

    Reply


  4. Created an empty variable just before that line which gets me past that error but I just get another.

    Starting catName [catId] …

    Fatal error: Uncaught exception ‘Exception’ with message ‘Notice: Undefined index: use_default in /var/www/vhosts/site/httpdocs/quickCatCreate.php on line 71

    (sorry for cluttering up your comments here).

    Reply


    • No problems ;)

      I’ve added a “$count = 0;” to the script for you, or you could just remove the “$count++;” as I don’t think you’ll need it.

      For the “use_defaults” error, just comment out the code (if you don’t need it).

      Reply



  5. Douglas

    Nice script! Thanks for creating it. :)

    I have a little problem, though … I did the bulk category import, but now I don’t like some of the categories I created.

    I ran your script again with a modified importCats.csv file, got the [i]Starting [category_name] [id] …Suceeded[/i] messages … but the original categories I bulk imported are still there.

    Does your script remove the existing categories before it imports the new ones? If not, do you know of a way I can delete all the categories in one fell swoop?

    There’s too many categories to delete manually, and I’m reluctant to delete the categories via PhpMyAdmin for fear there are other tables feeding off of the category table.

    Reply



  6. Douglas

    Thanks very much!

    Your handy scripts will save the Magento masses countless hours of valuable time.

    It’s a bit mind boggling that the Magento devs did not simply list the categories in a standard table with a “Select All” checkbox option like there is in the Manage Products section.

    Perhaps they were so enamored with their drag-and-drop feature for organizing the categories that they forgot about basic usability issues like the ability to delete multiple categories.

    Currently, on my dedicated and optimized sever with the cache disabled, it takes 15 seconds to delete a single category because of all the “please wait…” and “confirm delete” alerts. 15 seconds per category is pretty outrageous when you have hundreds of categories to delete.

    Whatever the reason for the oversight, we can rest easy knowing you are picking up the slack :)

    Reply


    • No problems ;)

      You always have the option of deleting the root category (which will delete all others beneath it) – so its *shouldn’t* be too slow.

      Have you considered applying this patch to speed up your admin …

      http://www.sonassi.com/knowledge-base/speeding-up-the-magento-admin/

      Also – when you say your dedicated server is “Optimised” – who did the optimisation, we consult for performance optimisation at a system level – as an option for those who choose to use their own hardware vs. http://sonassihosting.com .

      If you are interested at all – we could perform some preliminary tests and perhaps unleash a lot more performance than you are currently seeing – please get in touch http://sonassi.com/contact/

      Reply



  7. Thijmen

    It does import it, yet I don’t see it when I click “Manage Categories” in my Magento Backend. How to fix this?

    Reply


    • Hi Thijmen,

      I’m afraid this could be anything from your implementation to a cache issue. Without seeing for myself – I can’t really advise.

      Reply



  8. Brian

    Hi, great script! I was wondering how I would modify this so every category created is set to “active”?

    Reply



    • Brian

      NVM, I figured it out. For anyone else trying to do this, simply change the line:

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

      to

      $data['general][''is_active'] = $line[2];

      Then modify your csv file to include THREE columns:

      “parent cat id”,”new cat name”,”1″

      If you want it active, the third field should be “1″, inactive is “0″

      Reply


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

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

        Reply


  9. Hi,
    Scripts are great, just what I have been looking for.

    Is it possible to modify the “Quick script to batch create Magento categories” so I can write to the database the ID of the categories I have in my existing database? as I have gaps so not a sequential category ID.

    Stephen

    Reply


  10. Hi, I have added the active field as discussed in the messages, How would I modify to write the ID to the database please.

    Thanks Stephen

    Reply


  11. Hi,
    Added $data['general']['entity_id'] = $line[3]; this worked in the database table but the path field no longer filled properly and so added categories did not show up in admin.

    Any Ideas.

    Thanks
    Stephen

    Reply


  12. Just used this code in Magento 1.4.1.1 worked a charm, was able to manipulate and import over 1600 categories in less than an hour!

    Only problem I had was it timed out several times once it reached 300 secs. Rather than changing code I just edited the import file and continued with the import.

    Thanks
    Shragi

    Reply


    • Hi Shragi,

      It sounds like you hit your PHP timeout of 5 mins, just increase the value and in future it won’t pose the same issue.

      You can also remove the

      sleep(0.5);

      and test it without, we found some platforms need the sleep period, whilst others can happily run without.

      Reply


  13. Brilliant solution – thanks for posting it!

    Reply


  14. It looks like it works, but the categories do not show up. can you help me out?

    Starting Kid & baby [201] …Suceeded
    Starting (189)Bathing & care [202] …Suceeded
    Starting (28)Beds & bedding [203] …Suceeded
    Starting (12)Car seats [204] …Suceeded
    Starting (111)Decor [205] …Suceeded
    Starting (195)Feeding [206] …Suceeded
    Starting (78)Furniture [207] …Suceeded
    Starting (24)Gifts & keepsakes [208] …Suceeded
    Starting (18)Safety [209] …Suceeded
    Starting (9)Strollers [210] …Suceeded

    Reply



  15. Youssef

    Hello Ben,

    Great work, this is exactly what I’ve been looking for. I do need one modification, which is the addition of a column for the category picture.

    any idea how to modify your script to do so?

    thanks again man, really appreciate everything you’ve done for everyone.

    Reply


    • I can’t say I’ve tried it, so I’m not sure off the top of my head. I guess it would be similar to that of when you attach images to products via command line, so an improvised version of this *might* work.

      $category->setMediaGallery (array('images'=>array (), 'values'=>array ()));
      $category->addImageToMediaGallery ($imagePath, array ('image','small_image','thumbnail'), false, false);

      Reply


  16. First of all thanks for this great script.

    I ran the script and it shows as succeeded.

    However It does not show up in Magneto. It seems to be writing to the sql database as I can see it there however it is not showing up in magneto.

    Any advice? I would really appreciate it. breaking my head here :)

    Reply


    • Hi Ely,

      It could be that your root category ID doesn’t match that set in the script.

      Reply


      • Where in the script would I edit that?

        Reply


      • 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?

        Reply



  17. 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 .. ??

    Reply


  18. 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!

    Reply


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

    Reply



  20. sunil

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

    Reply



  21. 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

    Reply



  22. Mihau

    can i use this script to import sub categories?

    e.g.

    Apparel
    -Shoes
    –Mens
    –Womens

    Electronics
    -Cameras
    –Accessories
    –Digital Cameras

    Reply


    • 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.

      Reply


  23. 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?

    Reply


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

    :-0

    Reply



  25. manish

    It works without any error ….Thanks for the script

    Reply


  26. 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!

    Reply


  27. 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!

    Reply


  28. 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

    Reply


Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">