3

I have my own custom .phtml file that I would like to use for different collections of products. For example, I would like to use it to display the first n elements of category as well as the already seen products or related products. In addition I need to able to decide for each block to show/hide the price of the products.

Is it possible to do it with the core modules of Magento or should I extend the existing ones and write a new module?

1
  • Can you expand on 'I would like to use for different collections of products'. Does your template contains just product listings like the default list.phtml template or more page content? Are you showing more than one collection of products on the page or just one which has been modified? Commented Nov 26, 2014 at 12:30

1 Answer 1

1

You have a wonderful example for this in Magento itself. I am talking about Mage_Catalog module. In order to show different categories, Magento uses the same phtml file and same block itself !.

This is how Magento makes it possible. The template file that is used to show the product lists (in general) is app/design/frontend/base/default/catalog/product/list.phtml. The block which "controls" this template in almost all case is Mage_Catalog_Block_Product_List. How magento shows different product collection using the same block and same phtml file ? To get the answer, you need to have a look on the controller files that is processing different criterias. For an example, I am taking the CategoryController which will use to show different categories in frontend. Have a look on the viewAction (Module is Mage_Catalog).

 /**
 * Category view action
 */
public function viewAction()
{
    if ($category = $this->_initCatagory()) {
        $design = Mage::getSingleton('catalog/design');
        $settings = $design->getDesignSettings($category);
        ....
}

First of all it calls $this->_initCatagory(). So let us have a look on what is that method does.

protected function _initCatagory()
{
    Mage::dispatchEvent('catalog_controller_category_init_before', array('controller_action' => $this));
    $categoryId = (int) $this->getRequest()->getParam('id', false);
    if (!$categoryId) {
        return false;
    }
    ...
 }

There are lot of things happens here. BUt you need to look on this

 $this->getRequest()->getParam('id', false);

Here the controller retrieves the passing id through the url which is corresponding to a category. Using this category id, the controller loads the layout. The category view layout holds Mage_Catalog_Block_Product_List block and it then uses this category id to load the product collection. Have look on the method _getProductCollection() that comes inside this block class.

So in general, there are lot of methods to do this. If the collection that you need to show an entirely different and you still need to use the same template, then there is an alternative way. For each product collection, you need to create distinct block classes.

An example is shown below. Suppose your template is using a common function, let's say getMyCollection() to show the product. So your template somewhat looks like this.

FIle : app/design/frontend/<package>/<theme>/template/<namespace_module>/custom/product/list.phtml

  $collection = $this->getMyCollection();
  foreach ($collection as $item){
      //do something
  }

Now in your module, you have three blocks that looks like this.

File : app/code/local/Namespace/Module/Block/Custom/Product/List.php

<?php
class Namespace_Module_Block_Custom_Product_List extends Mage_Core_Block_Template
{
     protected $_collection = '';

     public function setListCollection($collection)
     {
         $this->_collection = $collection;
         return $this;
     }

     public function getListCollection($collection)
     {
         return $this->_collection = $collection;
     }
}

File : app/code/local/Namespace/Module/Block/Custom/Product/List/List1.php

    <?php
class Namespace_Module_Block_Custom_Product_List_List1 extends Namespace_Module_Block_Custom_Product_List
{

     public function setList1Collection()
     {
         //do some collection logic here
         $collection = Mage::getCollection('something/something')
                       ->addAttributeToFilter(...)
                       .....
                       ->load();
         //setting collection
         $this->setListCollection($collection);
     }

     public function getMyCollection()
     {
         return $this->getListCollection();
     }

}

File : app/code/local/Namespace/Module/Block/Custom/Product/List/List2.php

    <?php
class Namespace_Module_Block_Custom_Product_List_List2 extends Namespace_Module_Block_Custom_Product_List
{

     public function setList2Collection()
     {
         //do some collection logic here
         $collection = Mage::getCollection('something/something')
                       ->addAttributeToFilter(...)
                       .....
                       ->load();
         //setting collection
         $this->setListCollection($collection);
     }

     public function getMyCollection()
     {
         return $this->getListCollection();
     }

}

You can see that List1 and List2 has getMyCollection() method. BUt they return differnt collection, because we are setting different collection on the parent List block using corresponding setList{1,2}Collection() method.

Now you are declaring two blocks in your layout like this.

For Namespace_Modulename_ListController::list1Action()

 <block type="namespace_module/custom/product/list/list1" name="list1.list" as="some.alias" template="app/design/frontend/<package>/<theme>/template/<namespace_module>/custom/product/list.phtml" />

For Namespace_Modulename_ListController::list2Action()

 <block type="namespace_module/custom/product/list/list2" name="list2.list" as="some.other.alias" template="app/design/frontend/<package>/<theme>/template/<namespace_module>/custom/product/list.phtml" />

This will load two different product collection, but still uses same template.

Hope you get some idea now. So ultimately you need to decide which method is good for you and thus proceed.

Good Luck !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.