Copy Magento Category
Since first laying eyes on Magento, the open source eCommerce software, I been impressed by it’s power, flexibility and rigid code structure. But despite Magento’s almost endless list of strengths, it also has some significant weaknesses, that often leave me frustrated and confused. One such weakness is the apparent lack of any functionality in regards to copying products and categories.
I had created a category, with about 10 child categories. Now I just wanted to duplicate that category 5 times, rather than creating another 4 from scratch, each with 10 children (4×10=40 categories!). Rather than spend the next couple of hours adding categories, I knocked together this quick PHP script. Simply pass in the ID of the category you’d like to duplicate, and it will create a copy of the category, along with all of it’s child categories, as deep as they go!
Ideally, this would be a proper Magento module, but I’m just starting out with Magento. Give me 6 months, eh?!
To use the script, simply copy it into a file such as copycat.php in your Magento root directory and call it like so:
http://www.example.com/copycat.php?id=[CATEGORY ID TO COPY]
<?php if(!is_numeric($_GET['id']))die('Please specify a category ID'); $catId = $_GET['id']; $xml = simplexml_load_file('app/etc/local.xml'); $host = $xml->global->resources->default_setup->connection->host; $username = $xml->global->resources->default_setup->connection->username; $password = $xml->global->resources->default_setup->connection->password; $dbname = $xml->global->resources->default_setup->connection->dbname; $res = mysql_pconnect($host, $username, $password); mysql_select_db($dbname); $catsDone = 0; duplicate_entity($catId); echo $catsDone . ' Categories duplicated.'; function duplicate_entity($id, $parent_id = null){ global $catsDone; // Grab category to copy $sql = "SELECT * FROM catalog_category_entity WHERE entity_id = " . $id; $query_entity = mysql_query($sql); $entity = mysql_fetch_object($query_entity); if(!$parent_id)$parent_id = $entity->parent_id; mysql_query("INSERT INTO catalog_category_entity (entity_type_id, attribute_set_id, parent_id, created_at, updated_at, path, position, level, children_count) VALUES ({$entity->entity_type_id}, {$entity->attribute_set_id}, {$parent_id}, NOW(), NOW(), '', {$entity->position}, {$entity->level}, {$entity->children_count})"); $newEntityId = mysql_insert_id(); $query = mysql_query("SELECT path FROM catalog_category_entity WHERE entity_id = " . $parent_id); $parent = mysql_fetch_object($query); $path = $parent->path . '/' . $newEntityId; mysql_query("UPDATE catalog_category_entity SET path='". $path."' WHERE entity_id=". $newEntityId); foreach(array('datetime', 'decimal', 'int', 'text', 'varchar') as $dataType){ $sql = "SELECT * FROM catalog_category_entity_".$dataType." WHERE entity_id=" . $entity->entity_id; //die($sql); $query = mysql_query($sql); while ($value = mysql_fetch_object($query)){ mysql_query("INSERT INTO catalog_category_entity_".$dataType." (entity_type_id, attribute_id, store_id, entity_id, value) VALUES ({$value->entity_type_id}, {$value->attribute_id}, {$value->store_id}, {$newEntityId}, '{$value->value}')"); } } $sql = "SELECT entity_id FROM catalog_category_entity WHERE parent_id = " . $id; $query = mysql_query($sql); while ($entity = mysql_fetch_object($query)){ duplicate_entity($entity->entity_id, $newEntityId); } $catsDone++; } ?>

January 4th, 2011 at 7:40 pm
Thanks a lot for these my friend; not only was it helpfull in a direct sense, but also gave my an insight into Magento´s Inner Workings! Thanks!
May 20th, 2011 at 7:02 pm
Hi!
Works great, but is there a possibility that the products in the categories also can be copied?
Hope so…
May 27th, 2011 at 11:15 pm
Sounds interesting, which releases of Magento does it work with. Has anyone tried it?
May 27th, 2011 at 11:28 pm
Just tried it in Magento 1.4.1.1 – bloomin heck it works!
July 22nd, 2011 at 8:43 am
You are awsome.. I was looking to write a mysql script to duplicate all the categories… than i found this. Works great!
July 29th, 2011 at 6:49 pm
Great Work… Its save my lots of time.
Thanx a Lot…
August 12th, 2011 at 11:36 pm
ei… its six months later… where is the extension? lol (<—–Joke)
thanks for your work. Im trying right now
August 21st, 2011 at 12:42 pm
Just tried it in Magento 1.5. Great, it works
September 20th, 2011 at 4:54 pm
Awesome!!!
December 12th, 2011 at 11:40 am
Note, I wouldn’t use this approach. Should Magento ever change the table definitions, your code will break. Better is to use the API, see: http://stackoverflow.com/a/8472982/1025437
December 20th, 2011 at 5:18 pm
you are amazing! you just saved me a week!
January 17th, 2012 at 5:31 pm
Thanks for helpfully Script!
February 8th, 2012 at 6:32 pm
I do not think that this is working with 1.6.2 It says it was successful, but I cannot find the categories anywhere! lol
I hope you update this one day!
March 21st, 2012 at 8:37 pm
This worked like a charm. Great job and thanks for sharing.
April 4th, 2012 at 6:43 pm
Yeah! Works without a problem! tnx man!
April 27th, 2012 at 2:29 am
Using Magento ver. 1.5.1.0 and this works like a charm!
June 21st, 2012 at 12:47 pm
Hi,
I am getting the following error when trying this in Magento CE 1.6.1
Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource in /home6/tersdire/public_html/category_copy.php on line 31
I called the file category_copy.php
Any ideas?
June 27th, 2012 at 2:08 pm
Many thanks for posting this solution.
Tested this on Magento 1.7.0.1 and it need’s a small fix for certain NULL value’s,
@line;
[pre]
while ($value = mysql_fetch_object($query)){
mysql_query(“INSERT INTO catalog_category_entity_”.$dataType.” (entity_type_id, attribute_id, store_id, entity_id, value)
VALUES ({$value->entity_type_id}, {$value->attribute_id}, {$value->store_id}, {$newEntityId}, ‘{$value->value}’)”);
}
[/pre]
@change it to;
[pre]
if (is_null($value->value)) {
mysql_query(“INSERT INTO catalog_category_entity_”.$dataType.” (entity_type_id, attribute_id, store_id, entity_id, value)
VALUES ({$value->entity_type_id}, {$value->attribute_id}, {$value->store_id}, {$newEntityId}, NULL)”);
} else {
mysql_query(“INSERT INTO catalog_category_entity_”.$dataType.” (entity_type_id, attribute_id, store_id, entity_id, value)
VALUES ({$value->entity_type_id}, {$value->attribute_id}, {$value->store_id}, {$newEntityId}, ‘{$value->value}’)”);
}
[/pre]
Also it seems the children count doesn’t get updated, for that to be fixed too, change the following;
@line
[pre]
duplicate_entity($catId);
echo $catsDone . ‘ Categories duplicated.’;
[/pre]
@change to
[pre]
duplicate_entity($catId);
// Fix the children count for all (sub)categories
$sql = “CREATE TABLE catalog_category_entity_tmp LIKE catalog_category_entity”;
mysql_query($sql);
$sql = “INSERT INTO catalog_category_entity_tmp SELECT * FROM catalog_category_entity”;
mysql_query($sql);
$sql = “UPDATE catalog_category_entity cce
SET children_count =
(
SELECT count(cce2.entity_id) – 1 as children_county
FROM catalog_category_entity_tmp cce2
WHERE PATH LIKE CONCAT(cce.path,’%')
)”;
mysql_query($sql);
$sql = “DROP TABLE catalog_category_entity_tmp”;
mysql_query($sql);
echo $catsDone . ‘ Categories duplicated.’;
[/pre]
It works like a chamr here, now just to figure out how to copy product relations too
August 1st, 2012 at 10:07 am
good work actually, but don’t working when magento tables are using some prefix, so have to use a variable to get prefix of tables and then add it in front of every table. adding here so just someone can get help
September 10th, 2012 at 8:14 pm
great code ! But this not copy polish letters, how to fix it ?
September 27th, 2012 at 4:17 pm
Excellent work! I confirm this to work on the recent Magento 1.7.0.2. Just care a bit if you have a prefix set for your tables that you put it before the table names.
This code saved me 70$.
<3
January 28th, 2013 at 5:42 pm
How do you add the Mgn_ prefix to the code? Thanks
January 29th, 2013 at 1:40 am
Duplicate categories in magento 1.7.0.2 with this script works really like a charm. And it just takes a minute to install. And it doesnt mess all your tables like the Amasty extension. Great work!!!!!! There is no need for an extension.
February 13th, 2013 at 5:04 am
Works perfect! Thank you! Duplicated a root category with 3 levels of subs perfectly. Nice work.
February 24th, 2013 at 10:36 am
Works perfect! Thank you!
Great work !!!!!!
March 12th, 2013 at 11:26 pm
How do you add the prefix_magento03 to the code? Thanks
April 24th, 2013 at 6:34 am
Wow thanks! This will save a ton of time… One thing I see when the new categories are created in the display settings of the category “Layered Navigation Price Step” gets set to 0.0000 any idea how to set to default “Use Config Settings” Thanks again!
April 24th, 2013 at 7:38 am
I just used UPDATE catalog_category_entity_decimal SET value = NULL WHERE value = 0.0000, Thanks again for the script!