2

Subject is very concise: I need to show all products within given categories in a CMS page.

To accomplish this, I want to change list.phtml, since it's easy implementable and have a cool appearance.

To be more clear, I want my block like this:

{{block type="catalog/product_list" name="product_list" category_id="12,13,26" column_count="5" mode="list" template="catalog/product/multiple_list.phtml"}}

Is it possible? I'm trying in several ways, but just can't figure out the logic to use in list.phtml that fit in my needs.

By the way, I've tried these solutions, but they aren't exactly what I'm in need:

Points of interest:

  • Magento version: 1.9.2
  • Already showing products of single category
  • Listing products of given root category would fit, but doesn't work too (it's showing products of all the other root categories)

Edit 1: I have found a answer that comes real close to what I need:

<?php
/**
* Displays multiple category view templates along with the product list for it
*/
/* @var $this Mage_Core_Block_Template */

$category_ids     = explode(',', $this->getData('category_ids'));
$current_category = Mage::registry('current_category');

if ($current_category) {
Mage::unregister('current_category');
}

foreach ($category_ids as $id) {

$category = Mage::getModel('catalog/category')->load(trim($id));

if (!$category->getId()) {
    continue;
}

Mage::register('current_category', $category);

$product_list = $this->getLayout()->createBlock('catalog/product_list', 'product_list_'.$id, array('template' => 'catalog/product/list.phtml'));

echo $this
    ->getLayout()
    ->createBlock('catalog/category_view', 'category_'.$id, array('template' => 'catalog/category/view.phtml'))
    ->append($product_list, 'product_list')
    ->toHtml();

Mage::unregister('current_category');
}

if ($current_category) {
Mage::register('current_category', $current_category);
}

The problem now is that this code is showing all products in root category, instead of the products within category given. Yet it's showing all product lists in it's own block. I want to show all three product lists in same block.

Edit 2: Now I've got this:

<?php
/**
 * Displays multiple category view templates along with the product list for it
 */
/* @var $this Mage_Core_Block_Template */

$category_ids     = explode(',', $this->getData('category_ids'));
$current_category = Mage::registry('current_category');

if ($current_category) {
    Mage::unregister('current_category');
}

foreach ($category_ids as $it => $id) {

    $category = Mage::getModel('catalog/category')->load(trim($id));

    if (!$category->getId()) {
        continue;
    }

    Mage::register('current_category', $category);

    global ${"category_"$it} = $this->getLayout()->createBlock('catalog/product_list', 'product_list_'.$id, array('template' => 'catalog/product/list.phtml'));

    Mage::unregister('current_category');

}

foreach ($category_ids as $it => $id) {
        global array product_list ( array $product_list [, array ${"category_"$it}] );
}

Mage::register('current_category', 'category_1');

echo $this
    ->getLayout()
        ->createBlock('catalog/category_view', 'category_1', array('template' => 'catalog/category/view.phtml'))
        ->append($product_list, 'product_list')
        ->toHtml();

}

if ($current_category) {
    Mage::unregister('current_category');
}

This part of code should:

  • Create 3 arrays of products
  • Merge these 3 arrays into 1 "products_list"
  • Create 1 block as "view"
  • Echo all 3 arrays into same block.

But now, it just stops my CMS page, breaking all content page.

Edit 3:

I'm not sure about how to create my own block, or how to call a block defined by me, but following @fschmengler and @Wouter Steenmeijer, here's what I have now:

Layout Update XML:

<reference name="content">
    <block type="core/template" name="multiple_categories" template="catalog/category/list.phtml">
        <action method="setData"><key>category_ids</key><val>12,13,26</val></action>
     </block>
</reference>

file: app/code/local/starscream/default/block/multiple.php

content:

<?php
 protected function _getProductCollection()
    {
    $category_ids = $this->getCategoryIds();
    $productCollection = Mage::getModel('catalog/product')
        ->getCollection()
        ->addStoreFilter()
        ->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
        ->addMinimalPrice()
        ->addFinalPrice()
        ->addTaxPercents()
        ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
        ->addUrlRewrite()
        ->joinField(
            'category_id', 'catalog/category_product', 'category_id',
            'product_id = entity_id', null, 'left'
        )
        ->addAttributeToFilter('category_id', array(
            array('in' => array($category_ids)),
        ));

        return $productCollection;
    }
?>

I didn't find how to call this "multiple.php" block I created in my CMS page... Am I missing something?

Any help is appreciated.

6

Good question!

The trick here is to extend a block based on catalog/product_list.

I think the best way here is to add some xml to the "Layout Update XML" section.

<reference name="content">
    <block type="catalog/product_list" 
           name="multiple_categories" template="catalog/product/list.phtml">
        <action method="setCategoryIds"><category_ids>4,5,6,7</category_id></action>
    </block>
</reference>

Here you have to replace catalog/product_list with your created custom module block. SetCategoryIds sets the categoryids in this block so you can filter on them.

In product/list.phtml is this called to get the product collection:

    $_productCollection=$this->getLoadedProductCollection();

The trick here is to create a custom module that extends on catalog/product_list and replaces the function _getProductCollection.

If you want to know how to do that, please read this: read this thread

In this new block you add this function:

    protected function _getProductCollection()
    {
    $category_ids = $this->getCategoryIds();
    $productCollection = Mage::getModel('catalog/product')
        ->getCollection()
        ->addStoreFilter()
        ->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
        ->addMinimalPrice()
        ->addFinalPrice()
        ->addTaxPercents()
        ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
        ->addUrlRewrite()
        ->joinField(
            'category_id', 'catalog/category_product', 'category_id',
            'product_id = entity_id', null, 'left'
        )
        ->addAttributeToFilter('category_id', array(
            array('in' => array($category_ids)),
        ));

        return $productCollection;
    }

EDIT:

First, forget about the custom module. This is magento best pratice, since we dont want to edit the core. We will get back to that later.

You're block type now is core/template. The function getProductCollection doesn't exist in the block core/template. Have a look in this folder: app/code/mage/core/block/template.php

So you have to reference to another block. Ideally you want to create a custom module for this that extents the block type catalog/product_list. But as I said earlier, well get back to that later.

In the block catalog/product_list ( app/code/mage/catalog/product/list.php ) is the function _getProductCollection(). This is the function that every catalog pages uses to get the product collection. This is also the function you want to use. So change core/template with catalog/product_list.

Replace the function _getProductCollection() with the function I pasted above. You will see that it works!

Now that you know that the new function that you made works, you want to put this code in a new custom block. You do that to create a module with a block. Read this thread carefully to create a new block: Stackexchange link to create a custom block

Reason for creating a new block is that we dont want to edit the core of magento. When you update magento to the newest version the changes you have done are gone. Also its hard to keep track of the changes being done.

I hope you now better understand the magento block system!

  • Good answer. I changed the collection initialization to optimize it and load all required data for the list block (see magento.stackexchange.com/a/78308/243 ) – Fabian Schmengler Jan 15 '16 at 14:38
  • Thanks, obv thats the much better way. I should have made a note for that in my answer. – Wouter Steenmeijer Jan 15 '16 at 14:40
  • I am really sorry but I can't figure out how to accomplish what you've pointed. I'll update my answer with what I've made in my limited understanding, which is not working yet, so you can check it. – Carlos Eduardo Santos Jan 29 '16 at 15:26
0

Thanks to everyone who helped me in this quest.

I've found a ugly solution, which fits better than my first thoughts:

I created a new sub-category, mixing all products I wanted from those 3 categories.

Then I just used this brand new category as main, which shows products from different stores without code-changing.

I couldn't find a better or easier way, but it's working. If you have any ideas, please share!

Edit: @WouterSteenmeijer also works, and is way prettier, but requires a higher skill level. Thank you all!

  • Well, I have a better idea, see above :) What do you want me to do for you so that you mark my post as the correct answer, and not your own :) – Wouter Steenmeijer Feb 5 '16 at 13:33
  • You're pretty right, Wouter. Now I see your update. Thank you for your answer. It really works! @WouterSteenmeijer – Carlos Eduardo Santos Feb 8 '16 at 18:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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