Web Development Blog – Alphadigital

Tips and Experiences

Magento – Filter by multiple categories
Thursday, 11 de June de 2009

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"?>
<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”}}

  • Share/Bookmark

4 comentarios

  • criography 06.18.2009 - 10:24

    Oh man! you have no idea! You’ve just saved me couple of days of digging through core files and getting even more irritated with Magento;) Now I have to figure out how to do the same thing with attributes, add some nice mod_rewrite to it and pray everything works (;

  • Heriquet 06.24.2009 - 15:15

    Hi,

    Thanks for this usefull tutorial. I tried this but I got this error at pages load :

    Warning: Varien_Autoload::include(
    //////////////////ModuleName/Catalog/Model/Resource/Eav/Mysql4/Product/Collection
    ///////////////.php) [function.Varien-Autoload-include]: failed to open stream: No such file or directory i

    Do you know what could happen ?

    Thanks

    Heriquet

  • flash 07.05.2009 - 3:00

    Cool!

  • Dominik 08.19.2009 - 12:04

    Hi, thanks for your great tutorial, doesn’t quite work the way I’d like, but at the moment I’m still hopeful.

    @Heriquet

    The problem you describe comes up, because of the whitespace in the config.xml.

    ModuleName_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

    if you put the code above on a single line and delete all whitespace between the tags, the error should disappear

¿Qué opinas de este tema?