Как программно назначить категории для продуктов в magento


Я новичок в magento. В принципе, я хочу распределить несколько продуктов по нескольким категориям. Я следовал этому сообщению и сделал следующий код, который работает нормально:

   $collection = Mage::getModel('catalog/product')->getCollection();//my coustom collection
        $categorys_ids = array(1,2,3,4,5);//Array of ids etc 
        if ($categorys_ids != NULL && $collection->getData()!= NULL)
            {
                foreach ($collection as $product) 
                {
                        $categories_pd = $product->getCategoryIds();                              
                        $product->setCategoryIds(array_merge($product->getCategoryIds(),array($categorys_ids)));
                        $product->save();
                }
            }

Теперь главная проблема заключается в том, что когда я назначаю идентификатор категории для продуктов, это занимает много времени. У меня есть 200 продуктов, и это занимает до двух минут или около того, что является большим количеством времени.

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

3 6

3 ответа:

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

$categoryId = 6; 
$category = Mage::getModel('catalog/category')->setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID)->load($categoryId);
//get the current products
$products = $category->getProductsPosition();
//now attach the other products.
$newProductIds = array(1,2,3,4,5);
foreach ($newProductIds as $id){
    $products[$id] = 1;//you can put any other position number instead of 1.
}
//attach all the products to the category
$category->setPostedProducts($products);
//save the category.
$category->save();

Если вы хотите сделать это еще быстрее, вы можете сделать прямые вставки в таблице catalog_category_product.
Просто убедитесь, что вы переиндексируете, когда закончите.

Вот как я это сделал, используя некоторые функции быстрого управления массивами из более новых версий PHP:

<?php
require_once '../../app/Mage.php';
Mage::app();
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$storeCode = Mage::app()->getStore()->getStoreId();

function addProductsToCategoryId($mergeProductIds, $categoryId, $storeCode) {
    // load the $category by $categoryId
    $category = Mage::getModel('catalog/category')->setStoreId($storeCode)->load($categoryId);
    // build a flipped array of two merged arrays (1) array keys from flipped $mergeProductIds, (2) array keys from product_id keyed array in $category
    $categoryProductIds = array_flip(array_merge(array_keys(array_flip($mergeProductIds)),array_keys($category->getProductsPosition())));
    // combine array_keys from resulting merge with a matched index array filled with '0'
    // THIS resets position of product within category, change this logic if desired
    $categoryProductIds = array_combine(array_keys($categoryProductIds), array_fill(0, count($categoryProductIds), '0'));

    $category->setPostedProducts($categoryProductIds);
    $category->save();

    // optional
    // return $categoryProductIds;
}

// optional array of category IDs to test against for nin (not in) or in a find_in_set array test
// in the optional example line below, nin (not in) is used
$categoryIds = array(5,8,9,10,11,12,45,46);

$collectionIds = Mage::getModel('catalog/product')->getCollection()
    ->setStoreId($storeCode)
    // optional inclusion of join for category_id
    ->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id = entity_id', null, 'left')
    // optional logic to only gather ids that are, or are not in a given categoryIds array, nin (not in) is shown in example
    // ->addAttributeToFilter('category_id', array('nin' => array('finset' => $categoryIds)))
    // optional line to test whether product is associated to ANY category
    ->addAttributeToFilter('category_id', array('null' => true))
    // example qualifiers to affect gathered IDs
    ->addAttributeToFilter('sku', array('like' => 'M-H%'))
    ->addAttributeToFilter('sku', array('nlike' => '%E'))
    ->addAttributeToFilter('sku', array('nlike' => '%E#'))
    ->addAttributeToFilter('sku', array('nlike' => '%Euro'))
    ->addAttributeToFilter('sku', array('nlike' => '%Euro#'))
    ->getAllIds()
    ;

// if using a return value, you can set the results of this to a variable
// to perform further operations against the resulting data
addProductsToCategoryId($collectionIds, 8, $storeCode);

Пожалуйста, обратите внимание, что по умолчанию мой метод не сохраняет никаких позиций для продуктов в заданных вами категориях. Он вернет всем позициям значение по умолчанию '0'.

Прекрасно работает. Требует последующего переиндекса, быстрого добавления массы. Код немного сложен, поэтому объяснение кода в комментариях прямого контекста имело для меня больше смысла в этом случае.

Я включил много из необязательных дополнений здесь, но все они помечены как таковые и полностью объяснены.

Для меня работал следующий код:

include '../../app/Mage.php';
Mage::app('admin');
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

$product_id = Mage::getModel("catalog/product")->getIdBySku($sku);
$product = Mage::getModel('catalog/product')->load($product_id);
$product->setCategoryIds($category_id);
$product->save();