Home Magento eCommerce

Magento – Filter by multiple categories

7 July 2009 8 Comments

We know that we can call a block to show products in your home page or in any CMS page. We MUST specify category ID:

{{block type=”catalog/product_list” category_id=”5″
template=”catalog/product/list.phtml”}}

Now, what if I want to show products from multiple categories or simply show all my products?

Well, here’s what I did. I created a custom module to extend some core classes, and I did it this way:

Activate custom module

app/etc/modules/ModuleName_All.xml

<?xml version="1.0"?></pre>
<config>
<modules>
<ModuleName_Catalog>
<active>true</active>
<codePool>local</codePool>
</ModuleName_Catalog>
</modules>
</config>

Set up the module

Here, we set up our blocks and extend our Colletion class.

app/code/local/ModuleName/Catalog/etc/config.xml

<?xml version="1.0"?>
<config>
<modules>
<ModuleName_Catalog>
<version>0.1.0</version>
</ModuleName_Catalog>
</modules>
<global>
<blocks>
<ModuleName_catalog>
<class>ModuleName_Catalog_Block</class>
</ModuleName_catalog>
</blocks>
<models>
<catalog_resource_eav_mysql4>
<rewrite>
<product_collection>
ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
</product_collection>
</rewrite>
</catalog_resource_eav_mysql4>
</models>
</global>
</config>

Listcategories class

app/code/local/ModuleName/Catalog/Block/Product/Listcategories.php

class ModuleName_Catalog_Block_Product_Listcategories
extends Mage_Catalog_Block_Product_List{

//same function from Mage_Catalog_Block_Product_List
protected function _getProductCollection(){

// get simple product collection
$this->_productCollection = Mage::getModel('catalog/product')->getCollection();
$this->_productCollection->addAttributeToSelect('*');

// if we receive categories parameter we filter with our custom function addCategoriesFilter
// currently there's a addCategoryFilter, but only accepts 1 category
// if no param is passed, simply show everything
if($this->getCategories()!="")
$this->_productCollection->addCategoriesFilter($this->getCategories());

return $this->_productCollection;
}
}

function addCategoriesFilter

Now, we have to extend Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection class and add the addCategoriesFilter function:

app/code/local/ModuleName/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php

class ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection{

public function addCategoriesFilter($categories){

$alias = 'cat_index';
$categoryCondition = $this->getConnection()->quoteInto(
$alias.'.product_id=e.entity_id AND '.$alias.'.store_id=? AND ',
$this->getStoreId()
);

$categoryCondition.= $alias.'.category_id IN ('.$categories.')';

$this->getSelect()->joinInner(
array($alias => $this->getTable('catalog/category_product_index')),
$categoryCondition,
array('position'=>'position')
);

$this->_categoryIndexJoined = true;
$this->_joinFields['position'] = array('table'=>$alias, 'field'=>'position' );

return $this;

}
}

Now on a CMS page you call your block this way:


{{block type=”ModuleName_catalog/product_listcategories”  categories=”14,16,18″
template=”catalog/product/list.phtml”}}

Related posts:

  1. Top 3 Solutions when your Magento Categories are not displaying
  2. Magento Menu Customization with Product List
  3. Secret feature of Magento 1.3: Sharing same route name for different modules!
  4. How to show Category Products on Homepage
  5. Observer pitfalls of building serious modules in Magento

8 Comments »

  • Nacho said:

    Because a Magento’s bug if you put
    [...]

    ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

    [...]
    in two lines is not going to work.
    Leave as follow:

    ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

    By the way, really useful code! I love it!

  • Nacho said:

    sorry:

    ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

  • toutouille said:

    I’m sorry but i run magento 1.3.2 and your script doesn’t work.

    First : in magento 1.3.2 i use Mage instead ModuleName…

    Can you please explain better your function it will be great because i need this to work !!!!

    Help me my friend ! ;-)

  • Nacho said:

    Hi toutouille, because there is a bug in Magento, try to put the rewrite tags in just one line in the file: config.xml.

  • Remco said:

    Hi,

    I’ve also implemented (or tried to anyway) your code, but I can’t get it to work.
    I’ve already tried putting this line ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

    on a single line, but that didn’t help.
    I’m running magento 1.3.2.4

    Any suggestions?

    Thx in advance

  • Nacho said:

    Try this:

    ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

    if not, can u post the error to see what happen?

  • Allan Brown said:

    The custom SQL code (ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection) is not required, and infact it makes the collection class less useful.

    Insead you should simply use the existing addAttributeToFilter function, passing in the following:

    $$categoryId1 = 10;
    $$categoryId1 = 12;
    $this->_productCollection->addAttributeToFilter(
    \’category_ids\’,array(
    array(\’finset\’=>array($categoryId1)),
    array(\’finset\’=>array($categoryId2))
    )
    );

    This has the advantage of working even if products are assigned to more than one category. And can filter collections which have already been filtered by a seperate category.

  • modra ideja said:

    absolutely brilliant! exactly what i needed :)