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;
}
  • Pingback: Quick script to batch create Magento categories | Manchester … | Magento News()

  • Sam

    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.

    • Try also using:

      ini_set(’error_reporting’, E_ALL);
      ini_set(’display_errors’, 1)

  • Sam

    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.

  • Sam

    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

  • Sam

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

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

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

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

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

      https://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/

  • Thijmen

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

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

  • Pingback: Categorie()

  • Brian

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

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

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

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

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

  • 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

  • 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

  • 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

  • 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

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

  • Brilliant solution - thanks for posting it!

  • 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

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

    • 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); 
      
  • Ely

    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 🙂

    • Hi Ely,

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

      • Ely

        Where in the script would I edit that?

      • 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 FilesEasyPHP5.2.10wwwmagentoappcodecoreMageCoreModelConfig.php on line 1254

    this constant is defined in Product.php(Mage_Catalog_Model_Convert_Adapter_Product)

    any idea about this .. ??

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

  • 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

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

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

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

    :-0

  • manish

    It works without any error ....Thanks for the script

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

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

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

  • 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

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

  • kml

    works very great.... thank you very muuuuuchh 😀

  • 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

  • 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

  • Mathieu Kinosky

    Hello, Thank you for this script.
    However I have a question, is it possible to set the ID of the category?

    • sonassi

      Yes ... that's the whole point of the article - and one of the only two columns in the input CSV file.

      • Mathieu Kinosky

        The first column is the parent category.
        The second column is the name of the new category.
        I created a third column in the CSV file.
        It contains the ID of the new category.
        In the code I have:

        ....
        if (!empty($line[0]) && !empty($line[1]) && !empty($line[2])) {
        $data['general']['path'] = $line[0];
        $data['general']['name'] = $line[1];
        $data['general']['entity_id'] = $line[2];

        ....

        However, the ID is always generated automatically by magento ...

  • Mathieu Kinosky

    At the moment I still have not found a solution.
    I will update if I find, for people who want to put their ID CATEGORY.

    • I've got it to work so you can specify the category id yourself.

      Format of the importCats.csv:
      parent_category_id,category_name,category_id
      example: 3,subcat,5
      -> Creates a category with 'subcat' as name and 5 as category id. The parent category id is 3.

      The working script can be found on http://pastebin.com/JeFuzmwe.

      Hopefully it's useful for you and other people.

  • Alex

    Hello 🙂 I've followed the instructions to the letter but it doesn't work in Magento 1.7.0.2. The script runs and I get a success message for every category, but nothing shows up in the admin interface. Any help would be greatly appreciated.

  • sbm

    Thanks for this piece of art!! it works perfectly!

  • Ashwin

    Hi,

    I got the message Starting subcat [14] ...Suceeded but in admin panel , no category added. Help needed..

  • graffxdesign

    Awesome! Imported 120 in seconds! Thanks

  • Sander van Zuidam

    Nice script works but it's very slow for me, I am importing 150 categories with 5 fields. It will run more then 5 minutes.
    Is there a way to speed it up? Using magento 1.9

    • sonassi

      Better hosting?

      • Sander van Zuidam

        haha 🙂 well maybe indeed because it's on a vagrant local box we created. Will try it first on my normal server, sorry that might just be it.

  • Henrique Filgueiras

    hi, how can i put meta title, meta description, enable, url and display in menu using this great tutorial? please, answer faster you can, pleaseeeeee

    https://www.sonassi.com/knowledge-base/quick-script-batch-create-magento-categories/

    • sonassi

      Hey Henrique, just append `$data['general']['meta_description'] = "";` for each field as necessary.

      • Henrique Filgueiras

        sorry, but i dont understand it. can you show me or write a line with this information to be easier? Please, answer me. I need too much it =(

  • Henrique Filgueiras

    hi, now i get it, but i am brazilian and i need caracters like ç and now, magento doesnt support. how can i use this caracter importing csv?

  • Thx for sharing, it worked great after little tweeking. The most important thing for me was to set all categories as "active" and "is anchor" so i changed:
    $data['general']['is_active'] = 1;
    $data['general']['is_anchor'] = 1;

    and it all worked fine.

    I use v1.9.2.

    • Christer Johansson

      Hi,
      would you mind sharing what your "tweaking" was? I am trying to use this script, but my categories end up somewhere else in my site. I can see them in the DB, but not in admin or frontend.

      • Well the only things i did were the ones i wrote in my comment, setting them to active and anchor. U have to write the number of category that already exist...i think.

        It might be your csv formating is wrong? Another thing i changed was on line 10:

        while (($line = fgetcsv($file,null,';')) !== FALSE)

        this takes " ; " as seperator so u can have " , " in your category names.

  • Christer Johansson

    Hello,
    Thanx for a nice write up. Even though this is nearly 6 years later, it still works to some extent. I get the message that categories have been imported, and I see them in my database. But they do not show up in the admin interface, and is not visible at frontend. In my CSV I have 1 root category that gets imported and shows up, but the rest is just not there.

    I am using Magento 1.9.2.2

  • Athena Baguazhang

    anyone know if it works in a http://www.mysite.com/magento/ directory? I installed magento in a sub directory so wondering if that is causing a problem. Also I'm assuming what I'm supposed to visit would be http://www.mysite.com/magento/quickcatcreate.php? It just doesn't work, nothing at all comes up, not even a 404.

  • No10Count

    So just tried this on 1.9.2.2
    Getting nothing but a blank page.
    Returns nothing and nothing is added to data base (checked)
    Tried both this one and the one on Stack Overflow (http://stackoverflow.com/questions/34213371/csv-import-export-problems-in-magento/34267981#34267981)
    Put the php file within my magento folder and my csv file within var/import (created folder and made sure permissions)

    Ideas?

    Update - got error reporting working on it.
    INVALID HOST REQUEST (domain name) is what it is returning.

  • David

    Does it work with magento2 ? anyone tried it already?