Magento Filter Collection for Multiple Categories

Is there an easy way to filter a collection of products into several categories? Get all items in any of the listed categories? addCategoryFilter does not seem to resolve the array.

The only way to get collections for each interest category separately, and then combine them?

I understand that it was possible with something like

 addAttributeToFilter('category_ids',array('finset'=>array('1','2'))) 

or similar, but this is not possible, since 1.4.

Note. I am using 1.6, and if using it, I am using something like this:

 $product = Mage::getModel('catalog/product'); $_productCollection = $product->getCollection() ->addAttributeToSelect('*') ->addAttributeToFilter('status',1) ->addStoreFilter(); 
+6
source share
6 answers

Magento now works to get the Store, and in the store you can get categories from the store, for example $ oStoreCollection-> addCategoryFilter (array ('1', '2'));

I came across a solution that could help you found here:

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

The code used is as follows: Reinstall 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; } 

Then it is 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. 

NTN

+4
source

It uses a method that does not require kernel modifications. This is taken from this post with the addition of a group clause to handle duplicate product entries.

 $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'); 
+9
source

If you want to filter multiple categories using AND (so that the product appears in categories A, B and C, you need to have several connections:

 $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... ; 
+3
source

I managed to solve this problem (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;)

+1
source
  • Magento 1.8.0.0;
  • The flat directory is included in admin;
  • Make sure you cache the block in which you put this:
  • Do not add this to paid topics.
  • The inner join, hard-coded here, reproduces this:

    $ gallery-> 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
source

Filter Product Collection Using Multiple Category Identifiers

 $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 the product type ie type_id or change it as required.

0
source

Source: https://habr.com/ru/post/909457/


All Articles