以编程方式将Magento产品添加到类别中

时间:2011-06-27 10:32:42

标签: magento categories

我使用的是Magento 1.4.0.1。 我有超过21000个简单的产品,每个产品都进入一个类别。 我的网站有数百个类别。 某些产品属于多个类别。 我有什么方法可以以编程方式将产品添加到多个类别中吗?

7 个答案:

答案 0 :(得分:51)

在PHP代码中,您可以在导入它们时将它们放入类别中。

假设您有一个名为$ product的产品和一个名为$ category_id

的类别ID

您可以通过执行以下操作来设置产品所属的类别

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

如果该产品已有类别,并且您想再添加一个类别,那么您可以使用getCategoryIds()这样的内容:

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

或者,正如Joshua Peck在评论中所提到的,您可以使用category_api模型在类别中添加或删除产品,而不会影响其当前的类别分配:

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

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

答案 1 :(得分:2)

您可以编写一个模块(这需要时间,但可能更快地导入数据),或者您可以将某些内容与API结合在一起(较少涉及Magento编程,但导入数据的速度可能较慢)。

您已知道的起点,您的时间以及您需要多长时间运行更新的出发点应该决定您的选择。

以下是用于向类别添加产品的Magento API文档(请参阅页面底部的示例):

http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_category

答案 2 :(得分:1)

我最后因为某种懒惰的原因而最终使用API​​。这会将所有可见产品添加到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']));
  }
?>

答案 3 :(得分:1)

在查看Magento API之后:Magento通过以下方式将产品添加到类别中:

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;
}

获得所有签名产品:

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;
}

答案 4 :(得分:1)

以上最佳答案指向使用Mage::getSingleton('catalog/category_api') ->assignProduct($category->getId(),$p‌​roduct->getId());

无论如何,如果你要更新很多产品/类别,那么这个功能会很慢。

这是因为api函数assignProduct()

  • 仅接受1个产品/类别
  • 对于每次调用,它会加载产品和类别,然后保存类别
    (如果您需要多次更新同一类别,则速度非常慢)

例如,假设您要将10个产品分配到1个类别...它将加载并保存相同类别10次...
 (如果您确定产品ID是正确的,则加载所有实际上不需要的产品)

更快的方式
我提出了与api相同的以下功能,但只加载并保存类别一次

此函数接受一个数组作为参数$data,需要包含$category_id => array(all the products you want to assign)

形式的所有收集更改

根据您的需要定制它是微不足道的,例如,store_id的参数(默认情况下函数使用0)和产品的位置信息......

添加类别

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();
    }
}

删除类别

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();
    }
}

注意

保存类别会触发Category Flat DataCatalog URL Rewrites reindex(如果它们设置为update on save)。
这不是很快(API调用也一样)...
...因此您可能希望在运行更改之前将这些reindex设置为手动更新,然后在完成后对它们执行完全重新索引 (根据您更新的类别/产品数量,这可能是最佳选择)

答案 5 :(得分:0)

我们可以使用magento脚本以编程方式将多个产品分配到该类别。请创建一个类别数组,然后根据自定义属性或字段选择产品。

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

循环浏览产品并分配到类别,如下所示。

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

请参阅my tutorial,其中提供了逐步说明。

答案 6 :(得分:0)

为产品分配类别的最佳方式。 核心代码引用 - app\code\core\Mage\Catalog\Model\Resource\Category.php

$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$categoryProductTable = Mage::getSingleton('core/resource')->getTableName('catalog/category_product');
$productData = array();$position=0;
foreach ($_productCollection as $product) {
    $productData[] = array(
        'category_id' => (int)$catId1,
        'product_id'  => (int)$product->getId(),
        'position'    => (int)$position
    );
$productData[] = array(
        'category_id' => (int)$catId2,
        'product_id'  => (int)$product->getId(),
        'position'    => (int)$position
    );
}

$write->insertMultiple($categoryProductTable, $productData);