0

This question already has an answer here:

For a product page I'd like to show 1 random product from each of the 3 preselected categories. The final layout would be 3 products next to each other (1 from each category). Now I have read several topics about the random product issue, none of them however address the issue of having several single products from different categories.

I started by creating the code that would pick a random product from a specific category:

<?php
$catid = '338';
$category = new Mage_Catalog_Model_Category();
$category->load($catid);
$collection = $category->getProductCollection();
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$collection->getSelect()->order('rand()');
$collection->addStoreFilter();
$numProducts = 1;
$collection->setPage(1, $numProducts)->load();
?>

<?php foreach($collection as $product): ?>

<?php $product = Mage::getModel('catalog/product')->load($product->getId());
  echo $product->getName();
  echo $product->getShortDescription(); ?>
<?php endforeach; ?>
<?php endif; ?>

This works just fine. What would be the next step to get 1 product from the other 2 categories (say id 339 & 340)?

marked as duplicate by Sander Mangel, liyakat, Amit Bera, Sukeshini, brentwpeterson Sep 7 '15 at 18:11

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

1

An efficient solution for big catalogs is to first load all product ids from the three categories, then pick one randomly from each of them and finally load these products by ID.

This might seem counter-intuitive, but ORDER BY RAND() has serious performance issues, the larger the table is and it gets worse with joining all the EAV tables. See also: show random products from a category

Code

$categories = Mage::getResourceModel('catalog/category_collection')
    ->addFieldToFilter('entity_id', array('in' => [338, 339, 340]));
$productIds = array();
foreach ($categories as $category) {
    $candidateIds = $category->getProductCollection()->getAllIds();
    $productIds[] = $candidateIds[array_rand($candidateIds)];
}

$products = Mage::getResourceModel('catalog/product_collection')
    ->addMinimalPrice()
    ->addFinalPrice()
    ->addTaxPercents()
    ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
    ->addUrlRewrite()
    ->addIdFilter($productIds);

Now $products is the product collection with three random products and all data that you need to display it in a product list template.

  • Thanks for this, I do seem to get a parse error on the first line I'm not sure how to solve... – Badger Sep 7 '15 at 15:27
  • Sorry, I updated the code, it should work now – Fabian Schmengler Sep 7 '15 at 15:29
0
$category_ids = array(338,339,340);
$productids_from_each_category = array();

// loading category and one product from resp category and storing id in the variable called $productids_from_each_category
foreach($category_ids as $category_id){
    $_productCollection = Mage::getModel('catalog/category')->load($category_id)
                            ->getProductCollection()
                            ->addAttributeToFilter('status', 1)
                            ->addAttributeToFilter('visibility', 4);

    $_productCollection->getSelect()->order('RAND()');
    $_productCollection->getSelect()->limit(1);
    $collection = $_productCollection->getFirstItem();

    if($collection->getId()){
        $productids_from_each_category[] = $collection->getId();
    }
}

// loading products collection
$product_collection = Mage::getModel('catalog/product')
                ->getCollection()                
                ->addAttributeToFilter('entity_id', array('in' => $productids_from_each_category))
                ->addAttributeToSelect('*');

echo "<pre>"; print_r($product_collection->getData());
  • The only thing i would add to this is a check before adding it to the productids_from_each_category just to make sure there is actually a result. – Smartie Sep 7 '15 at 14:57
  • yes i am updating the answer now – Pradeep Sanku Sep 7 '15 at 14:59
  • done updated my answer – Pradeep Sanku Sep 7 '15 at 14:59
  • 1
    Although this might work it's an extremely heavy script and should in no way be used on a production shop. We're talking about multiple joining queries that are used to retrieve 3 products – Sander Mangel Sep 7 '15 at 15:07
  • 1
    Yes, and also adding the rand() means the query cannot be cached – Smartie Sep 7 '15 at 15:10

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