Программно добавить продукты в Magento в категориях

Я использую Magento 1.4.0.1. У меня есть более 21000 простых продуктов, каждый из которых входит в одну категорию. На моем сайте сотни категорий. Некоторые продукты относятся к нескольким категориям. Есть ли способ для меня, чтобы программно добавить товар в несколько категорий?

7 ответов


в PHP-коде вы можете поместить их в категорию во время импорта.

скажем, у вас есть продукт под названием $product и идентификатор категории под названием $category_id

вы можете установить категории, к которым принадлежит продукт, выполнив следующие действия

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

если продукт уже имеет категории, и вы хотите добавить еще один, то вы можете использовать getCategoryIds() такой:

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

или, как говорил Джошуа Пек в комментариях, вы можете использовать the category_api модель для добавления или удаления продукта из категории, не затрагивая его текущие назначения категорий:

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

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

Я просто хочу добавить, что вы можете удалить и добавить с помощью getSingleton category API:

чтобы удалить продукт из категории:

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

добавить продукт в категорию:

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

это не будет перезаписывать какие-либо категории продукт уже находится в


вы можете написать модуль (который занимает время, но потенциально быстрее при импорте ваших данных) или вы можете что-то вместе с API (меньше вовлечения программирования Magento, но потенциально медленнее при импорте ваших данных).

ваша отправная точка того, что вы уже знаете, насколько ценно ваше время и как часто вам нужно будет запускать обновление, должна определить ваш выбор.

вот документация Magento API для добавления продуктов в категории (см. пример внизу страницы):

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


Ну, я закончил делать это с 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;
}

и получать все asigned продукты:

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

мы можем назначить несколько продуктов категории программно, используя сценарии 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();
}

см. мой учебник что дает пошаговое объяснение.


лучший ответ для Mage::getSingleton('catalog/category_api') ->assignProduct($category->getId(),$p‌​roduct->getId());

в любом случае эта функция довольно медленная, если у вас есть много продуктов/категорий для обновления.

это потому, что функция api assignProduct():

  • только примите 1 продукт / категорию во время
  • для каждого вызова он загружает продукт и категорию, а затем сохраните категория
    (очень медленно, если вам нужно обновить одну и ту же категорию несколько раз )

например, предположим, что вы хотите присвоить 10 продуктов 1 категории ... он загрузится и сохранит ту же категорию 10 раз ...
(и загрузите весь продукт, который на самом деле не требуется, если вы уверены, что идентификаторы продукта исправлены)

быстрее
Я придумал функцию ниже, которая такая же, как 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();
    }
}

Примечание

сохранение триггера категории the Category Flat Data и Catalog URL Rewrites reindex ( если они установлены как update on save ).
Это не совсем быстро (вызов API делает то же самое ) ...
... таким образом, вы можете установить эти reindex для обновления вручную перед запуском изменений, а затем сделать полный reindex на них после
(в зависимости от количества категорий/продуктов, которые вы обновляете, это может быть лучшим вариантом )