We not only created a lot of new categories, we deleted a lot of old categories and renamed some of them as well. Now the issue was to correctly assigning products to appropriate categories. We were provided product csv with three columns (category,sku,category-code). category-code was for SAP admins, so they can update their inventory according to code. But we need other two columns only. Here is the shell script I wrote which runs smoothly and does the work for me :-)
<?php /** * Get the csv with category name and product sku and assign product to that category and it's parent. * * @category Technooze * @package Assign Product To A Category And It's Parents * @copyright Copyright (c) 2012 Technooze.com * @author Damodar Bashyal * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * */ require_once dirname(__FILE__) . '/../app/Mage.php'; class Mage_Shell_setCategory { private $_categories = array(); private $_csv = array(); public function run() { if((empty($this->_csv)) && (file_exists($csv = Mage::getBaseDir('var') . DS . 'import' . DS . 'new-categories.csv'))){ if (($handle = fopen($csv, "r")) !== FALSE) { $row = 1; $sku = $category = $categoryCode = 0; while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { if($row++ == 1){ $data = array_flip($data); $sku = $data['sku']; $category = $data['category']; $categoryCode = $data['category-code']; continue; } $this->_csv[] = array( 'sku' => $data[$sku], 'category' => $data[$category], 'categoryCode' => $data[$categoryCode], ); } fclose($handle); } } $path = array(); $rows = count($this->_csv); $row = 1; foreach($this->_csv as $k => $v){ echo "\n\rProcessing row {$row} of {$rows}\n\r"; $row++; $categoryName = $v['category']; $sku = $v['sku']; // Get Category Id and it's parent category IDs so, we can assign the product to these categories // Check to see if this category information has been already fetched if(isset($this->_categories[$categoryName])){ $path = $this->_categories[$categoryName]; } // if not, pull information about the selected category else { $categoryCollection = Mage::getResourceModel('catalog/category_collection') ->addFieldToFilter('name', array('eq' => $categoryName)) ->addAttributeToSelect('name') ->load(); foreach ($categoryCollection as $category) { $cpath = $category->getPath(); if(!empty($cpath)){ $path = explode('/', $cpath); // remove the first element as this is root category array_shift($path); // now save this category and path, so we can re-use if needed. $this->_categories[$categoryName] = $path; } } } echo ($msg = $categoryName . '=>' . implode(',',$path)) . "\n\r"; Mage::log($msg); // load the product collection filtered by sku $collectionConfigurable = Mage::getResourceModel('catalog/product_collection') //->addAttributeToFilter('type_id', array('eq' => 'configurable')) ->addAttributeToFilter('sku', array('eq' => $sku)) ->addAttributeToSelect('name') ->addAttributeToSelect('sku') ->load(); if(count($collectionConfigurable)){ // now set the category ids to selected product. foreach ($collectionConfigurable as $product) { if(count($path)){ //$product = Mage::getModel('catalog/product')->load($product->getId()); $product->setCategoryIds($path); $product->save(); } echo ($msg=$product->getName() . '=>' . $product->getSku() . '=>' . $product->getId()) . "\n\r"; Mage::log($msg); } } else { echo ($msg='ERROR:: Invalid SKU ' . $sku) . "\n\r"; Mage::log($msg); } } echo "YaY! All Done!!!\n\r"; } } umask(0); /* not Mage::run(); */ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); error_reporting(E_ALL ^ E_NOTICE); $shell = new Mage_Shell_setCategory(); $shell->run(); // end of file:: shell/productToCategory.php
This is how i run using php command line:
shell > php productToCategory.php
Sample CSV: var/import/new-categories.csv
sku,category-code,category
AAA01RD,C-TT,t-shirts + tops
AAA03NV,C-TT,t-shirts + tops
AAA04PK,C-TT,t-shirts + tops
As, the product was always assigned to one category, the script supports one base category per product. It can be modified to support multiple base categories. It assigns to supplied category and it's parents.
And this is sample output:
Processing row 1 of 12401
t-shirts + tops => 2,3,323,336
Circus Poster Tee=>AAA01RD=>420
Also, the log is saved on the system log file.