I am using Magento 1.4.0.1. I have over 21000 simple products, each entered into a single category. There are hundreds of categories in my site. Some products belong in mult
The best above answer points to use Mage::getSingleton('catalog/category_api')
->assignProduct($category->getId(),$product->getId());
Anyway that function is pretty slow in case you have a lot of products/categories to update.
This is because the api function assignProduct():
For example suppose you want to assign 10 products to 1 category ... it gonna load and save the same category 10 times ...
( and load all product that is not actually required if you are sure you product ids are corrects)
A faster way
I came up with the below function that is the same as the api one but it loads and save the category only one time.
This function accept an array as parameter $data that needs to contains all collect changes in the form of $category_id => array(all the products you want to assign)
It is trivial to customize it as for your needs adding, for example, a parameter for store_id ( the function use 0 by default) and position information to the products ...
Add category
function assignCategories($data)
{
foreach ($data as $cat_id => $products_ids) {
/** @var $category Mage_Catalog_Model_Category */
$category = Mage::getModel('catalog/category')
->setStoreId(0)
->load($cat_id );
$positions = $category->getProductsPosition();
foreach ($products_ids as $pid) {
$positions[$pid] = null;
}
$category->setPostedProducts($positions);
$category->save();
}
}
Remove category
function removeProduct($data)
{
foreach ($data as $cat_id => $products_ids) {
/** @var $category Mage_Catalog_Model_Category */
$category = Mage::getModel('catalog/category')
->setStoreId(0)
->load($cat_id);
$positions = $category->getProductsPosition();
foreach ($products_ids as $pid) {
unset($positions[$pid]);
}
$category->setPostedProducts($positions);
$category->save();
}
}
note
Saving the category trigger the Category Flat Data and Catalog URL Rewrites reindex ( if they are set as update on save ).
This is not exactly fast ( the API call does the same ) ...
... so you may want to set these reindex to update manually before running your changes and then do a full reindex on them after
( depending on the number of categories/product you are updating this could be the best option )