Question

In my Magento installation, I have created two root categories, one for each website.

Let's say in my UK website, it use root category that has categoryID 2. In my US website, it uses root category that has categoryID 100.

I can successfully assign a product to a category within root category 2. And the problem is, if I want to give this product to another category within root category 100, it will just remove the product from root category 2, and then add to root category 100. This is not what I want, I want to keep the product in both categories, instead of moving it around.

This is the code I'm using to update products. What should I change so it will add the product to a new category while still keeping the product in the old category?

    private function updateProductData(array $data, ProductAbstract $product)
{

    $_rootcatID = $this->util->getRootCategoryIdByWebsiteId($data['dataarea']);
    $category = \Mage::getModel('catalog/category')
        ->getCollection()
        ->addAttributeToFilter('custom_category', 'IG' . $data['category_id'])
        ->addFieldToFilter('path', array('like'=> "1/$_rootcatID/%"))
        ->getFirstItem();

    $path = '';
    if ($category->getId()) {
        $path = $category->getPath();
        $path = str_replace("1/$_rootcatID/", '', $path);
        $path = explode('/', $path);

        foreach ($path as $idx => $segment) {
            $path[$idx] = $this->getCategoryName($segment);
        }

        $path = implode('/', $path);
    }
    $name = str_replace('||', "\n", $data['name']);
    $name = trim($name);
    $name = str_replace("\n", " - ", $name);

    //Take multiple websites into consideration
    // Get website for existing SKU.
    $_product = \Mage::getModel('catalog/product');
    $_product->load($_product->getIdBySku($data['sku']));
    $websiteIds = $_product->getWebsiteIds();

    foreach($websiteIds as $websiteId){
        $_websites .= \Mage::getModel('core/website')->load($websiteId)->getData("code") . ",";
    }

    $_websites = $_websites . $this->util->getWebsiteCode($data['dataarea']);

    $product->set('name', $name)
        ->set('sku', $data['sku'])
        ->set('is_in_stock', 1)
        ->set('visibility', DataInterface::VISIBILITY_CATALOG_SEARCH)
        ->set('tax_class_id', 'Taxable Goods')
        ->set('store', $this->util->getStoreCode($data['dataarea']))
        ->set('websites',$_websites)
        ->set('weight', $data['net_weight'])
        ->set('url_key', $this->getUrlKeyFromName($data['name']))
        ->set('is_qty_decimal', $data['qty_is_decimal'])
        ->set('status', 1);

    //add the product to the correct category by id
    //(if 2 categories has the same name, it might use the wrong category which might me inactive)
    if ($category->getId()) {
      $product->set('category_ids', $category->getId());
    } else {
      $product->set('categories', $path);
    }

    foreach ($this->plainAttributes as $plain) {
        $product->set($plain, $data[$plain]);
    }
}
Was it helpful?

Solution

You need to load the product in the context of the website ID to save the category for that product (against that store). Something like

$allStores = Mage::app()->getStores();

foreach ($allStores as $_storeId => $storeValue)
{
    $_theStoreId = Mage::app()->getStore($_storeId)->getId();

    $_product = Mage::getModel('catalog/product')->load(1234)->setWebsiteId($_theStoreId);

    $storeSpecificCategories = $_product->getCategoryIds();

    // add new category but keep existing
    $storeSpecificCategories[] = '234567';

    $_product->setData('category_ids', $storeSpecificCategories);
    $_product->save();

}

Looking at your initial collection, you should also limit the SQL response by setting the pagesize and currentpage. Otherwise, it might load a larger dataset that you expect into memory:

$category = \Mage::getModel('catalog/category')
    ->getCollection()
    ->addAttributeToFilter('custom_category', 'IG' . $data['category_id'])
    ->addFieldToFilter('path', array('like'=> "1/$_rootcatID/%"))
    ->setPageSize(1)
    ->setCurPage(1)
    ->getFirstItem();
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top