Programmatically add Magento products to categories

后端 未结 7 1862
执念已碎
执念已碎 2020-12-24 14:31

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

相关标签:
7条回答
  • 2020-12-24 14:48

    I just want to add that you can remove and add with getSingleton category API:

    To Remove product from category:

    Mage::getSingleton('catalog/category_api')->removeProduct($category->getId(),$p‌​roduct->getId());
    

    To Add Product to Category:

    Mage::getSingleton('catalog/category_api')->assignProduct($category->getId(),$p‌​roduct->getId());
    

    This will not overwrite any categories the product is already in

    0 讨论(0)
  • 2020-12-24 14:53

    After looking into the Magento API: Magento adds products to categories in the following way:

    public function assignProduct($categoryId, $productId, $position = null, $identifierType = null)
    {
        $category = $this->_initCategory($categoryId);
        $positions = $category->getProductsPosition();
        $productId = $this->_getProductId($productId);
        $positions[$productId] = $position;
        $category->setPostedProducts($positions);
    
        try {
            $category->save();
        } catch (Mage_Core_Exception $e) {
            $this->_fault('data_invalid', $e->getMessage());
        }
    
        return true;
    }
    

    And getting all the asigned products:

    public function assignedProducts($categoryId, $store = null)
    {
        $category = $this->_initCategory($categoryId);
    
        $storeId = $this->_getStoreId($store);
        $collection = $category->setStoreId($storeId)->getProductCollection();
        ($storeId == 0)? $collection->addOrder('position', 'asc') : $collection->setOrder('position', 'asc');;
    
        $result = array();
    
        foreach ($collection as $product) {
            $result[] = array(
                'product_id' => $product->getId(),
                'type'       => $product->getTypeId(),
                'set'        => $product->getAttributeSetId(),
                'sku'        => $product->getSku(),
                'position'   => $product->getPosition()
            );
        }
    
        return $result;
    }
    
    0 讨论(0)
  • 2020-12-24 15:00

    In PHP code you can put them into the category while you are importing them.

    Say you have a product called $product and a category ID called $category_id

    You can set the categories which a product belongs to by doing the following

    $categories = array($category_id);
    $product->setCategoryIds($categories);
    $product->save();
    

    If the product already has categories and you'd like to add one more then you can use getCategoryIds() like this:

    $categories = $product->getCategoryIds();
    $categories[] = $categoryId;
    $product->setCategoryIds($categories);
    $product->save();
    

    Or, as mentioned by Joshua Peck in the comments, you can use the category_api model to add or remove a product from a category without affecting it's current category assignments:

    Mage::getSingleton('catalog/category_api')
      ->assignProduct($category->getId(),$p‌​roduct->getId());
    
    Mage::getSingleton('catalog/category_api')
      ->removeProduct($category->getId(),$p‌​roduct->getId());
    
    0 讨论(0)
  • 2020-12-24 15:03

    We can assign multiple products to the category programmatically using magento scripts. Please create an array of the categories and the select the products based on the custom attribute or field.

    $newproducts = $product->getCollection()->addAttributeToFilter(array(array('attribute'=>'attribute_label', 'eq'=> 'attribute_id')));
    

    Loop through the products and assign to category as shown below.

    $newCategory = array( $list[0] , $list[$key]); 
    foreach ($newproducts as $prod)
    {
        $prod->setCategoryIds(array_merge($prod->getCategoryIds(), $newCategory));
        $prod->save();
    }
    

    Please refer my tutorial which gives a step by step explanation.

    0 讨论(0)
  • 2020-12-24 15:06

    The best above answer points to use Mage::getSingleton('catalog/category_api') ->assignProduct($category->getId(),$p‌​roduct->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():

    • only accept 1 product/category at time
    • for every call it loads the product and the category and then save the category
      ( very slow in case you need to update the same category multiple times )

    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 )

    0 讨论(0)
  • 2020-12-24 15:10

    Well I ended up doing this with the API for some reason of laziness. This adds all the visible products into the category with ID 146:

    <?php
      $client= new SoapClient('http://www.example.com/api/soap/?wsdl', array('trace' => 1, "connection_timeout" => 120));
    
      // Can be added in Magento-Admin -> Web Services with role set to admin
    
      $sess_id= $client->login('apiuser', 'apikey');
    
      // Get the product list through SOAP
      $filters = array('visibility' => '4', 'status' => '1');
      $all_products=$client->call($sess_id, 'product.list', array($filters));
    
      // Now chuck them into category 146
    
      foreach($all_products as $product)
      {  //var_dump($product);
          echo $product['sku']."\n";
          $doit=$client->call($sess_id, 'category.assignProduct', array('146', $product['sku']));
      }
    ?>
    
    0 讨论(0)
提交回复
热议问题