Some custom Blocks to help you show products

Posted on 07. Oct, 2008 by Fido in Development, Magento, Module

I have a few custom blocks I’ve written / copied and tweaked from various posts on Magento’s forums. I noticed they are pretty universal in how they grab, filter and return a product collection to be used in various template files (.phtml files). The blocks below should all work from List.phtml (app\design\frontend\default\default\template\catalog\product\list.phtml).

These are Block files and are most appropriately used within the Catalog/Product area. (See my post on creating a custom module - these files won’t be overwriting any other class but can stand alone).

Be aware that the code below contains code for custom attributes that I happened to use on a project. They most likely will not be the same your particular instances. (the Bestseller block should not be affected by this issue).

Bestseller.php


//bestseller module - grabs from all products, returns in order of total quantity ordered
class Mage_Catalog_Block_Product_Bestseller extends Mage_Catalog_Block_Product_Abstract
{
public function __construct()
{
parent::__construct();

$storeId    = Mage::app()->getStore()->getId();

$products = Mage::getResourceModel('reports/product_collection')
->addOrderedQty()
->addAttributeToSelect(array('name', 'price', 'small_image', 'short_description', 'description', 'author'))
->setStoreId($storeId)
->addStoreFilter($storeId)
->setOrder('ordered_qty', 'desc');

Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($products);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($products);

//$products->setPageSize(6)->setCurPage(1);

$this->setProductCollection($products);
}
}
?>

SpecificCategory.php


<?php
//Grab products from a specific category - in this case category 13
class Mage_Catalog_Block_Product_Bookclub extends Mage_Catalog_Block_Product_Abstract
{
public $_collection;

protected function _getProductCollection()
{
$storeId    = Mage::app()->getStore()->getId();
$product    = Mage::getModel('catalog/product');
$category	= Mage::getModel('catalog/category')->load(13); //category whos ID is 13

$visibility = array(
Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
);

$products   = $product->setStoreId($storeId)
->getCollection()
->addAttributeToFilter('visibility', $visibility)
->addCategoryFilter($category)
->addAttributeToSelect(array('name', 'price', 'small_image', 'short_description', 'description', 'author'), 'inner') //example custom attributes
->setOrder('created_at', 'desc')
->addAttributeToSelect(array('special_price', 'special_from_date', 'special_to_date'), 'left')
;

$this->_collection = $products;
return $this->_collection;

}

public function getCurrentCategory() {
return Mage::getModel('catalog/category')->load(13);
}

public function getProductCollection() {
return $this->_getProductCollection();
}
}
?>

SpecificCategoryLayer.php


<?php
/*This is the same as above but grabs the product collection from the 'catalog/layer' singleton.
I've had to use this in some pre-1.1.x Magento builds because the above code version created some
weird errors when users edited any product in the backend (resulting in front end server time outs). That error was probably local to that Magento build, but it resulted in this code.

Note on use: You can only set the category of the layer once per page request, so you CANNOT use
this block of code multiple times on one page unless you want to repeat products from the same
category multiple times on one page.
*/
class Mage_Catalog_Block_Product_Bookclub extends Mage_Catalog_Block_Product_Abstract
{
public $_collection;

protected function _getProductCollection()
{
$storeId    = Mage::app()->getStore()->getId();
$product    = Mage::getModel('catalog/product');
$layer = Mage::getSingleton('catalog/layer');

$category	= Mage::getModel('catalog/category')->load(13); //category by ID

$layer->setCurrentCategory($category);
$visibility = array(
Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
);

$products = $layer->getProductCollection()
->addAttributeToSelect('author', 'inner')		//example custom attributes
->addAttributeToSelect('shelf_talker', 'inner')
->setOrder('created_at', 'desc');

$this->_collection = $products;
return $this->_collection;

}

public function getCurrentCategory() {
return Mage::getModel('catalog/category')->load(13);
}

public function getProductCollection() {
return $this->_getProductCollection();
}
}
?>

These blocks do not represent all there is to making use of them. As mentioned, these should all work with “List.phtml” in the Catalog module design files, but you might want to create your own template.

The easiest way to implement these and make them usable is to add them to a Mage folder within the Local code folder (rather than core):
app/code/local/Mage/Catalog/Block/Product/Bestseller.php

This lets you skip the step of creating a custom module in order to use a simple block who’s only purpose is to list a category of products (or bestsellers in this case).

Tags: , , ,

8 Comments

[...] grabs a product collection. In this case, we are able to set the category id to 3. (See the post on custom blocks to help you get a feel for what this might look [...]

Rem

17. Nov, 2008

Hi,

Nice post, could have a lot of potential but can you advice please on how to further use the Bestseller class after you save it on /app/code/local/Mage/Catalog/Block/Product/Bestseller.php ?

Thanks a lot!

Fido

17. Nov, 2008

The blocks should all work from List.phtml (app\design\frontend\default\default\template\catalog\product\list.phtml).

You can then set this block anywhere, using something like:

or within the system CMS:

{{block type=”catalog/bestseller” template=”catalog/product/list.phtml”}}

Note that the “type” and “template” attributes will change depending on where you save your block and template.

Richard

22. Jan, 2009

I’m trying to get this to work but I’m not sure if I’m doing this correctly.

ok, I created a used.php in directory (local/Mage/Catalog/Block/Product/)

Then I copied and pasted your code for “specificcategory.php” into used.php and edited lines:

class Mage_Catalog_Block_Product_Bookclub

to read

class Mage_Catalog_Block_Product_Used

and inputed my category id in the two lines

Then I attempted to set the block in a static block reading:

{{block type=”catalog/product_used” template=”catalog/product/list.phtml”}}

I thought that would do the trick but I’m getting a sql error basically saying it didn’t find the category.

Fatal error: Call to a member function count() on a non-object in C:\webserver\htdocs\lovetheprice\app\design\frontend\default\blank\template\catalog\product\list.phtml on line 35

What do you think?

Fido

22. Jan, 2009

It looks like we need to look at list.phtml and see where the “count” function is being call (and on what). List.phtml might be expecting that function to be available when it is not in your “used.php” block

matt

09. Feb, 2009

Thanks for sharing this code. Any tips on how to extend it to filter through more than one category? I have items in two categories (neither of which are sub-categories), and I’m trying to call addCategoryFilter two times on the same product collection but get an SQL error …

cheers

Fido

09. Feb, 2009

Matt, have you attempted: “->addCategoryFilter(array(’cat1′, ‘cat2′))” ?

Passing an array might give you the results you want if you have not tried this already (versus using “addCategoryFilter” twice).

I also suggest looking at the newest blog post here as it gives a more in depth look using one of these blocks (using the Magento toolbar)

matt

09. Feb, 2009

Hi Fido,

Thanks for the idea. Unfortunately ->addCategoryFilter(…) doesn’t take an array. There’s even a second parameter to create an aliased indexing name so that a clash doesn’t occur, and I’ve managed to call the function with any errors, but the results don’t change so I’m not sure if it’s even working or not.

This “filter by multiple categories” issue seems to be a popular one in the Magento forums. I’ll take a look at your newest post, but if you have time to address multi-category filtering, I know many will appreciate it! :)

Thanks again.

Leave a reply