【发布时间】:2011-09-23 09:48:23
【问题描述】:
我正在使用 Magento 1.4.0.1。 我有超过 21000 个简单的产品,每个都进入一个类别。 我的网站上有数百个类别。 有些产品属于多个类别。 有什么方法可以让我以编程方式将产品添加到多个类别中?
【问题讨论】:
标签: magento categories
我正在使用 Magento 1.4.0.1。 我有超过 21000 个简单的产品,每个都进入一个类别。 我的网站上有数百个类别。 有些产品属于多个类别。 有什么方法可以让我以编程方式将产品添加到多个类别中?
【问题讨论】:
标签: magento categories
您可以编写一个模块(这需要时间,但在导入数据时可能会更快),或者您可以将一些东西与 API 放在一起(较少涉及 Magento 编程,但在导入数据时可能会更慢)。
你已经知道什么的起点、你的时间有多么宝贵以及你需要多久运行一次更新应该决定你的选择。
这是用于将产品添加到类别的 Magento API 文档(参见页面底部的示例):
http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_category
【讨论】:
在 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 在 cmets 中提到的,您可以使用 category_api 模型在类别中添加或删除产品,而不会影响其当前的类别分配:
Mage::getSingleton('catalog/category_api')
->assignProduct($category->getId(),$product->getId());
Mage::getSingleton('catalog/category_api')
->removeProduct($category->getId(),$product->getId());
【讨论】:
Mage::getSingleton('catalog/category_api')->removeProduct($category->getId(),$product->getId()); 和 Mage::getSingleton('catalog/category_api')->assignProduct($category->getId(),$product->getId()); 这不会覆盖产品已经在的任何类别。
由于某种懒惰的原因,我最终使用 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']));
}
?>
【讨论】:
查看 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;
}
【讨论】:
我只想补充一点,您可以使用 getSingleton 类别 API 删除和添加:
从类别中删除产品:
Mage::getSingleton('catalog/category_api')->removeProduct($category->getId(),$product->getId());
将产品添加到类别:
Mage::getSingleton('catalog/category_api')->assignProduct($category->getId(),$product->getId());
这不会覆盖产品已有的任何类别
【讨论】:
assignProduct/removeProduct 调用之后运行类别/产品重新索引,因此对于分配大量产品/类别而言,这不是一个可持续的解决方案。
我们可以使用 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,它给出了一步一步的解释。
【讨论】:
以上最佳答案点使用Mage::getSingleton('catalog/category_api')
->assignProduct($category->getId(),$product->getId());
无论如何,如果您有很多产品/类别要更新,该功能会很慢。
这是因为api函数assignProduct():
例如,假设您要将 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 Data 和Catalog URL Rewrites 重新索引(如果它们设置为update on save)。
这不是很快(API 调用也是如此)...
...因此您可能希望在运行更改之前将这些重新索引设置为手动更新,然后在之后对它们进行完整的重新索引
(取决于您要更新的类别/产品的数量,这可能是最佳选择)
【讨论】:
将类别分配给产品的最佳方式。 来自核心代码的引用 - 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);
【讨论】: