Magento filter product collection by multiple categories

前端 未结 6 1712
故里飘歌
故里飘歌 2020-12-09 13:56

Is there an easy way to filter a product collection by multiple categories? To get all items in any of the listed categories? addCategoryFilter doesn\'t seem to

相关标签:
6条回答
  • 2020-12-09 13:58

    I managed to resolve this (after much trial and error) with the following code:

    $collection = Mage::getModel('catalog/product')->getCollection();
    $collection->addAttributeToFilter('status', 1);
    $collection->addAttributeToSelect(array('name','sku','price','small_image'));
    
    // Filter by multiple categories
    $collection->joinField('category_id','catalog/category_product','category_id','product_id=entity_id',null,'left');
    $data_cats = $this->getRequest()->getParam('categories');
    // Or $data_cats = array(85,86,87,88);
    
          $filter_cats = array();
          foreach ($data_cats as $value_cats) {
             $filter_cats[] = array(
             'attribute' => 'category_id',
             'finset'    => $value_cats
          );
    }
    
    $collection->addAttributeToFilter($filter_cats);
    

    Hope this helps someone ;)

    0 讨论(0)
  • 2020-12-09 14:05

    If you want to filter on multiple categories, using AND (so a product must be in categorie A, B and C to show up, you need to have multiple joins:

    $products = Mage::getModel('catalog/product')->getCollection()
        ->joinField('category_id_1', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')
        ->joinField('category_id_2', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')
        ->addAttributeToFilter('category_id_1', array('eq' => 358))
        ->addAttributeToFilter('category_id_2', array('eq' => 252))
    // etc...
    ;
    
    0 讨论(0)
  • 2020-12-09 14:05

    Filter Product Collection using multiple category ids

    $all_categories = array('3','13','113');   
    $productCollection = Mage::getModel('catalog/product')->getCollection();
    $productCollection->joinField('category_id', 'catalog/category_product', 'category_id', 
                        'product_id = entity_id', null, 'left')
                      ->addAttributeToSelect('*')
                      ->addAttributeToFilter('type_id', array('eq' => 'simple'))
                      ->addAttributeToFilter('category_id', array($all_categories));
    foreach($productCollection as $product)
    {
        echo $product->getId() .$product->getName() . "<br/>";
    }
    

    You can remove the condition for product type i.e type_id or modify it as per requirement.

    0 讨论(0)
  • 2020-12-09 14:07

    Here's a method that doesn't require modifications to core. It's taken from this post with the addition of the 'group' clause to handle duplicate product records.

    $categories = array(7,45,233);
    
            $collection = Mage::getModel('catalog/product')->getCollection()
                ->addAttributeToSelect('*')
                ->joinField('category_id',
                    'catalog/category_product',
                    'category_id',
                    'product_id=entity_id',
                    null,
                    'left')
                ->addAttributeToFilter('category_id', array('in' => $categories));
            $collection->getSelect()->group('e.entity_id');
    
    0 讨论(0)
  • 2020-12-09 14:15

    The way Magento works now, is to get the Store, and on the store, you can get the categories from the storecollection like $oStoreCollection->addCategoryFilter(array('1','2'));

    I came across a solution that might help you, found here at:

    http://www.magentocommerce.com/boards/&/viewthread/201114/#t329230

    The code they use, looks like this: Override Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection, and add the following methods:

    public function addCategoriesFilter($categories)
        {
            $this->_productLimitationFilters['category_ids'] = $categories;
    
            if ($this->getStoreId() == Mage_Core_Model_App::ADMIN_STORE_ID) {
                $this->_applyZeroStoreProductLimitations();
            } else {
                $this->_applyProductLimitations();
            }
    
            return $this;
        }
    
        protected function _applyProductLimitations()
        {
            $this->_prepareProductLimitationFilters();
            $this->_productLimitationJoinWebsite();
            $this->_productLimitationJoinPrice();
            $filters = $this->_productLimitationFilters;
    
            // Addition: support for filtering multiple categories.
            if (!isset($filters['category_id']) && !isset($filters['category_ids']) && !isset($filters['visibility'])) {
                return $this;
            }
    
            $conditions = array(
                'cat_index.product_id=e.entity_id',
                $this->getConnection()->quoteInto('cat_index.store_id=?', $filters['store_id'])
            );
            if (isset($filters['visibility']) && !isset($filters['store_table'])) {
                $conditions[] = $this->getConnection()
                    ->quoteInto('cat_index.visibility IN(?)', $filters['visibility']);
            }
    
            // Addition: support for filtering multiple categories.
            if (!isset($filters['category_ids'])) {
                 $conditions[] = $this->getConnection()
                    ->quoteInto('cat_index.category_id=?', $filters['category_id']);
                if (isset($filters['category_is_anchor'])) {
                    $conditions[] = $this->getConnection()
                        ->quoteInto('cat_index.is_parent=?', $filters['category_is_anchor']);
                }
            } else {
                $conditions[] = $this->getConnection()->quoteInto('cat_index.category_id IN(' . implode(',', $filters['category_ids']) . ')', "");
            }
    
            $joinCond = join(' AND ', $conditions);
            $fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
            if (isset($fromPart['cat_index'])) {
                $fromPart['cat_index']['joinCondition'] = $joinCond;
                $this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
            }
            else {
                $this->getSelect()->join(
                    array('cat_index' => $this->getTable('catalog/category_product_index')),
                    $joinCond,
                    array('cat_index_position' => 'position')
                );
            }
    
            $this->_productLimitationJoinStore();
    
            Mage::dispatchEvent('catalog_product_collection_apply_limitations_after', array(
                'collection'    => $this
            ));
    
            return $this;
        }
    
        protected function _applyZeroStoreProductLimitations()
        {
            $filters = $this->_productLimitationFilters;
    
            // Addition: supprot for filtering multiple categories.
            $categoryCondition = null;
            if (!isset($filters['category_ids'])) {
                $categoryCondition = $this->getConnection()->quoteInto('cat_pro.category_id=?', $filters['category_id']);
            } else {
                $categoryCondition = $this->getConnection()->quoteInto('cat_pro.category_id IN(' . implode(',', $filters['category_ids']) . ')', "");
            }
    
            $conditions = array(
                'cat_pro.product_id=e.entity_id',
                $categoryCondition
            );
            $joinCond = join(' AND ', $conditions);
    
            $fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
            if (isset($fromPart['cat_pro'])) {
                $fromPart['cat_pro']['joinCondition'] = $joinCond;
                $this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
            }
            else {
                $this->getSelect()->join(
                    array('cat_pro' => $this->getTable('catalog/category_product')),
                    $joinCond,
                    array('cat_index_position' => 'position')
                );
            }
    
            return $this;
        }
    

    It then gets called like this:

    $collection = Mage::getModel('catalog/product')->getCollection()
                            ->addAttributeToSelect('*')
                            ->distinct(true) // THIS IS WHAT YOU NEED TO ADD
                            ->addCategoriesFilter($category->getAllChildren(true)); // Make sure you don't forget to retrieve your category here.
    

    HTH

    0 讨论(0)
  • 2020-12-09 14:20
    • Magento 1.8.0.0;
    • Flat catalog enabled in admin;
    • Make sure you've cached the block in which you'll place this;
    • Don't add this in paid themes ..
    • The inner join hard-coded here reproduces this:

      $collection->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());

      without 'cat_index.category_id=2'

    $category = Mage::getModel('catalog/category')->load(100);
    $allChildsIds = $category->getAllChildren($category);
    
    $visibility = Mage::getModel('catalog/product_visibility');
    
    $collection = Mage::getResourceModel('catalog/product_collection');
    $collection = $this->_addProductAttributesAndPrices($collection)
      ->addStoreFilter()
      ->setFlag('do_not_use_category_id', true)
      ->setFlag('disable_root_category_filter', true)
      ->addAttributeToSort('created_at', 'desc');
    
    $whereCategoryCondition = $collection->getConnection()
      ->quoteInto('cat_index.category_id IN(?) ', $allChildsIds);
    $collection->getSelect()->where($whereCategoryCondition);
    
    $conditions = array();
    $conditions[] = "cat_index.product_id = e.entity_id";
    $conditions[] = $collection->getConnection()
      ->quoteInto('cat_index.store_id = ? ', Mage::app()->getStore()->getStoreId());
    $conditions[] = $collection->getConnection()
      ->quoteInto('cat_index.visibility IN(?) ', $visibility->getVisibleInCatalogIds());
    
    $collection->getSelect()->join(
      array('cat_index' => $collection->getTable('catalog/category_product_index')),
      join(' AND ', $conditions),
      array()
    );
    
    $collection
      ->setPageSize(3)
      ->setCurPage(1);
    
    $collection->load();
    
    0 讨论(0)
提交回复
热议问题