1

I need some help. I have the following category structure

category>subcagtegory>subsubcategory

The parent is an empty category that serves as a landing page. I need to display a list of random products from all the subcategories and subsubcategories on the parent landing category. Right now I have the following Random.php

class Mage_Catalog_Block_Product_List_Random extends Mage_Catalog_Block_Product_List
{
    protected function _getProductCollection()
    {
        if (is_null($this->_productCollection)) {
            $categoryID = $this->getCategoryId();
            if($categoryID)
            {
              $category = new Mage_Catalog_Model_Category();
              $category->load($categoryID);
              $collection = $category->getProductCollection();
            } else
            {
              $collection = Mage::getResourceModel('catalog/product_collection');
            }
            Mage::getModel('catalog/layer')->prepareProductCollection($collection);
            $collection->getSelect()->order('rand()');
            $collection->addStoreFilter();
            $numProducts = $this->getNumProducts() ? $this->getNumProducts() : 3;
            $collection->setPage(1, $numProducts)->load();

            $this->_productCollection = $collection;
        }
        return $this->_productCollection;
    }
}

and I call it on the parent's category "Custom Layout Update" like this:

<reference name="content">
     <block type="catalog/product_list_random" name="product.list.random" template="catalog/product/random.phtml">
        <action method="setCategoryId"><category_id>3</category_id></action>
        <action method="setColumnCount"><count>5</count></action>
        <action method="setNumProducts"><num_products>20</num_products></action>
    </block>
</reference>

What I need is to be able to specify a category ID in the XML just as I do now. But instead of listing products from one parent category (as it does now), I need to list products from all of its subcategories and subsubcategories. I believe I need an array of some sort but I am a PHP n00b so need help writing clean code.

1

3 Answers 3

1

Configure the parent category as anchor category. Anchor categories automatically include items from their subcategories.

screenshot

On an unrelated note, ORDER BY RAND() is unperformant because it results in a resource intensive temp table copy. It has to load all results into a temporary table, assign a random number to each row and then sort without any index. Instead we retrieve all ids (this is faster and the amount of data is managable even for large catalogs), pick some randomly and retrieve these rows directly.

To do so, replace:

Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$collection->getSelect()->order('rand()');
$collection->addStoreFilter();
$numProducts = $this->getNumProducts() ? $this->getNumProducts() : 3;
$collection->setPage(1, $numProducts)->load();

with:

$collection
    ->addStoreFilter()
    ->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());

$numberOfItems = $this->getNumProducts() ? $this->getNumProducts() : 3;
$candidateIds = $productCollection->getAllIds();

$choosenIds = [];
$maxKey = count($candidateIds)-1;
while (count($choosenIds) < $numberOfItems)) {
  $randomKey = mt_rand(0, $maxKey);
  $choosenIds[$randomKey] = $candidateIds[$randomKey];
}

$collection->addIdFilter($choosenIds);
$collection
    ->addMinimalPrice()
    ->addFinalPrice()
    ->addTaxPercents()
    ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
    ->addUrlRewrite();
0

If you have:

category>subcagtegory1>subsubcategoryX

Why don't you just put all the products of subsubcategoryX in the subcategory1? So you only need to define custom methods that support arrays within the XML.

1
  • the only category that has products is the subsubcategory. the parent and grandparent are just landing pages that lead to subsubcategory. any other ideas?
    – Dan
    Commented Aug 9, 2015 at 16:33
0

This isn't tested, so take it with a grain of salt, but I think it should work : EDIT : Code revised.

class Mage_Catalog_Block_Product_List_Random extends Mage_Catalog_Block_Product_List
{
    protected function _getProductCollection()
    {
        if (is_null($this->_productCollection)) {
            $categoryID = $this->getCategoryId();
            if($categoryID)
            {
                // Get array of subcategory ids
                $catModel = Mage::getModel('catalog/category');
                $parentCat = $catModel->load($categoryID);
                $children= explode(',',$parentCat->getChildren());


                // Use the array to filter the collection
                $collection = Mage::getModel('catalog/product')->getCollection();

                $collection->joinField(
                    'category_id', 'catalog/category_product', 'category_id',
                    'product_id = entity_id', null, 'left'
                )
                    ->addAttributeToFilter('category_id', array('in' => $children))
                    ->addAttributeToSelect('*');
            $collection->getSelect()->group('entity_id');
            } else {
                $collection = Mage::getResourceModel('catalog/product_collection');
            }
            Mage::getModel('catalog/layer')->prepareProductCollection($collection);
            $collection->getSelect()->order('rand()');
            $collection->addStoreFilter();
            $numProducts = $this->getNumProducts() ? $this->getNumProducts() : 3;
            $collection->setPage(1, $numProducts)->load();

            $this->_productCollection = $collection;
        }
        return $this->_productCollection;
    }
}
8
  • I just tried the code but magento breaks and spits out an error. There has to be an easier way to just get a product collection of all child categories.
    – Dan
    Commented Aug 9, 2015 at 18:17
  • What's the error?
    – AreDubya
    Commented Aug 9, 2015 at 18:29
  • Looking at your custom xml, etc, I don't know if this is applicable to you, but with the parent set to 'is anchor = true', you would get subcats prods on a normal magento page. See this : stackoverflow.com/questions/8624728/… Again - don't think it's applicable to your current situation, but if it is that's the easiest way.
    – AreDubya
    Commented Aug 9, 2015 at 18:42
  • actually the root category is not an anchor category so this doesn't apply to me. I need to display a product collection of all child categories (anchor and non-anchor) of a root non-anchor category.
    – Dan
    Commented Aug 9, 2015 at 19:59
  • Copy that. The code above has an issue with the model. Best I could do off the top of my head, but wrong. If the question is still open I will take a better look when I get home.
    – AreDubya
    Commented Aug 9, 2015 at 20:01

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.