2

I am currently using the following code to display four products in a random order. It works, but I'd like to limit the results to a particular category or an array of categories. How would I go about implementing this change?

Thanks!

<?php $products = Mage::getModel('catalog/product')->getCollection();
  $products->addAttributeToSelect(array('name', 'thumbnail', 'price')); //feel free to add any other attribues you need.
  Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($products);
  Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($products); 
  $products->getSelect()->order('RAND()');
  $products->getSelect()->limit(4);
  foreach ($products as $product)  : ?>
  <div class="three columns">
    <div class="product_container ">
      <div class="feat_prod_cont">
        <h4 class="feature_product_title"><a href="<?php echo $product->getProductUrl()?>"><?php echo $product->getName()?></a></h4>
        <a href="<?php echo $product->getProductUrl()?>"><img class="thumbnail" src="<?php echo Mage::helper('catalog/image')->init($product, 'thumbnail')->resize(93, 100)?>" alt=" "></a>
        <div class="prod_details_featured">
          <h3 class="price">$199.99</h3>
          Free Shipping Free Stove
        </div>
        <div class="buy_btn"><a href="<?php echo Mage::helper('checkout/cart')->getAddUrl($product); ?>">ADD TO CART</a></div>
      </div>
    </div>
  </div>
<?php endforeach; ?>

3 Answers 3

2

The previous answers focus on filtering a product collection by a single category. This is also covered by Get product collection from a category id.

I'll explain how to filter by "an array of categories" as requested, and how to optimize the "4 random products" query.

Filter by array of categories

Unfortunately the product collection does not provide any method to filter by multiple categories at once. It would only take a little change in Mage_Catalog_Model_Resource_Product_Collection but let's not go the core rewrite way and join+filter manually instead:

$storeId = Mage::app()->getStore()->getId();
$categoryIds = [ /* Category IDs */];
$productCollection = Mage::getModel('catalog/product')->getCollection();

$joinConditions = array(
    'cat_index.product_id=e.entity_id',
    $productCollection->getConnection()->quoteInto('cat_index.category_id IN (?)', $categoryIds),
    $productCollection->getConnection()->quoteInto('cat_index.store_id=?', $storeId)
);
$productCollection->getSelect()->join(
    array('cat_index' => $this->getTable('catalog/category_product_index')),
    $joinConditions,
    array('cat_index_position' => 'position')
);

Last but not least, add any other filters or attributes to select as needed and load the product collection.

This is what's usually needed for a product list:

$productCollection
    ->addStoreFilter()
    ->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
    ->addMinimalPrice()
    ->addFinalPrice()
    ->addTaxPercents()
    ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
    ->addUrlRewrite();

This prepares the product collection to load the necessary data to display prices, the product link and any attributes configured as "used in product listing", but not more.

Show 4 random items of collection

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 candidate ids (this is faster and the amount of data is managable even for large catalogs), pick some randomly and retrieve these rows directly. You can read about it in detail in my blog: http://www.schmengler-se.de/en/2015/09/show-random-products-in-magento-you-are-doing-it-wrong/

To do so, insert this code after the category and visibility filters for the collection have been applied:

$numberOfItems = 4;
$candidateIds = $productCollection->getAllIds();

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

$productCollection->addIdFilter($choosenIds);
1
<?php
$catid = '3'; //your category id
$category = new Mage_Catalog_Model_Category();
$category->load($catid); // this is your category id!
$collection = $category->getProductCollection();
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$collection->getSelect()->order('rand()');
$collection->addStoreFilter();
$numProducts = 4;
$collection->setPage(1, $numProducts)->load();
foreach($collection as $product) {
$product = Mage::getModel('catalog/product')->load($product->getId()); /* Load Products by ID*/
echo $product->getName();
echo $product->getShortDescription();
endforeach;
?> 
1

It should be something like this(just load your category by needed ID)

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

And then add in your code

$products->addCategoryFilter($category);

The reason why you can't use addCategoryFilter(15) because parameter for addCategoryFilter() (from class Mage_Catalog_Model_Resource_Product_Collection) should be a Mage_Catalog_Model_Category object.

3
  • Hey there, Sergei! I added this (didn't remove any code but added this) and it's still not filtering it to the category ID I give it. Could it be something I've done wrong? May 3, 2013 at 5:50
  • Try this one, it works for me $products = Mage::getModel('catalog/product')->getCollection() ->addCategoryFilter($category) ->addAttributeToSelect(array('name', 'thumbnail', 'price'));
    – Sergei Guk
    May 3, 2013 at 16:54
  • Also you can try $cat_id = 15; $products = Mage::getModel('catalog/product')->getCollection() ->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id = entity_id', null, 'left') ->addAttributeToFilter('category_id', $cat_id) ->addAttributeToSelect(array('name', 'thumbnail', 'price')); And also check this link for multiple categories (I've not tested this) blog.chapagain.com.np/…
    – Sergei Guk
    May 3, 2013 at 17:03

Your Answer

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

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