Another alternative:
In the example, $categoryIds
is an array of category Ids. (I usually use $collection->getFlag('category_ids')
but changed for this example, see explanantion lower down)
$currentStoreId
is populated by any means that can get the current store id. (in my observer event I use $collection->getFlag('store_id')
)
$conditions = array(
'cat_index.product_id=e.entity_id',
$collection->getConnection()->quoteInto('cat_index.category_id IN (' . $categoryIds . ')', "")
);
if (!Mage::app()->getStore()->isAdmin()) {
$conditions[] = $collection->getConnection()->quoteInto('cat_index.store_id=?', $currentStoreId );
}
$joinCond = join(' AND ', $conditions);
$fromPart = $collection->getSelect()->getPart(Zend_Db_Select::FROM);
if (isset($fromPart['cat_index'])) {
$fromPart['cat_index']['joinCondition'] = $joinCond;
$collection->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
} else {
$collection->getSelect()->join(
array('cat_index' => $collection->getTable('catalog/category_product_index')), $joinCond, array('cat_index_category_id' => 'category_id')
);
}
I use the above code in an observer to filter with multiple categories AFTER the built in call Mage_Catalog_Model_Resource_Product_Collection::_applyProductLimitations()
does it's thing, as it sends an event called 'catalog_product_collection_apply_limitations_after'
The _applyProductLimitations
method essentially applies the filters set by the call to addCategoryFilter
.
By using a flag in the $collection
, it is an easy matter to store the multiple category ids for the observer.
Thus whenever I have the need to filter by multiple categories, I set a flag on the collection at some point
an example would be to rewrite Mage_Catalog_Model_Category::getProductCollection()
public function getProductCollection() {
$collection = parent::getProductCollection();
$collection->setFlag('category_ids',array(19,243,42,54)); //the array of values can be from somehwre, this hard coded array serves purely as an example
return $collection;
}
Now, when magento fires the event, my code replaces the category filter with my multiple filter :)
This is essentially how my Dynamic Category Products module does its thing for its multiple category filters.
Ref The core code of addCategoryFilter
:
/**
* Specify category filter for product collection
*
* @param Mage_Catalog_Model_Category $category
* @return Mage_Catalog_Model_Resource_Product_Collection
*/
public function addCategoryFilter(Mage_Catalog_Model_Category $category)
{
$this->_productLimitationFilters['category_id'] = $category->getId();
if ($category->getIsAnchor()) {
unset($this->_productLimitationFilters['category_is_anchor']);
} else {
$this->_productLimitationFilters['category_is_anchor'] = 1;
}
if ($this->getStoreId() == Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID) {
$this->_applyZeroStoreProductLimitations();
} else {
$this->_applyProductLimitations();
}
return $this;
}