Category Page Product Sorting

In this blog we will see basics of how to product sorting in category page and how to setup different sorting type.

We will also see how to set default sorting in product collection e.g if we want to sort products in ascending order by price,name etc.
By default the product sorting drop down in category page is show here Magento Admin Manage Category Display Settings Tab. Suppose we want to add/remove sorting options from the drop down go to the Admin -> Manage Categories and then edit the current category, there go to the “Display Settings” Tab. There will see the list of sorting attributes that show up in the category page drop down, and you can also see an option to select default sorting method.

Magento Admin Category Page Display Setting Tabs

Magento Admin Category Page Display Setting Tabs

If we want to add more sorting options, i.e we have some more attributes which we want to have option to sort by. For this go to Catalog -> Attributes -> Manage Attributes in admin. Open the edit page of the attribute which you want to add to sort. There in the “Fontend Properties” box you will get the option for “Used for Sorting in Product Listing”, make this drop down as Yes and then this attribute will show up on the Manage Category Page. Magento Admin Manage Attributes

Custom Product Sorting In Category Page

Support we want to add a custom product sorting option, like sort product by created_date or update_date. For this we need to do some coding.
Lets take a simple example first i.e need to sort product by created_date. First will add an option to our drop down.
For this open the file Mage_Catalog_Model_Config and we need to make changes to the function getAttributeUsedForSortByArray().

 public function getAttributeUsedForSortByArray()
    {
        $options = array(
            'position'  => Mage::helper('catalog')->__('Position'),
            'created_at'  => Mage::helper('catalog')->__('Product Creation Date')
        );
        foreach ($this->getAttributesUsedForSortBy() as $attribute) {
            /* @var $attribute Mage_Eav_Model_Entity_Attribute_Abstract */
            $options[$attribute->getAttributeCode()] = $attribute->getStoreLabel();
        }

        return $options;
    }

You need to override this class to make the changes
Next we need to make changes to the our collection, so that products are sorted by our custom drop down value. But right now, since ‘created_at’ is already a product attribute, we don’t need to make changes anywhere else.
Let’s take another example where we will sort products by number of reviews. Since review is not a product attribute, we need to make changes to our product collection. Rest everything is same as far as adding option to drop down is concerned.
For this open file Mage_Catalog_Block_Product_List_Toolbar and around line 221 there is a function ‘setCollection’. You need to override this class in your module and then change the ‘setCollection’ function to

public function setCollection($collection)
	{
		$this->_collection = $collection;

		$this->_collection->setCurPage($this->getCurrentPage());

		// we need to set pagination only if passed value integer and more that 0
		$limit = (int)$this->getLimit();
		if ($limit) {
			$this->_collection->setPageSize($limit);
		}
                if($this->getCurrentOrder() == 'review'){
        	$this->_collection->sortByReview($this->getCurrentDirection());
        }
        else if ($this->getCurrentOrder()) {
            $this->_collection->setOrder($this->getCurrentOrder(), $this->getCurrentDirection());
        }
		return $this;
	}

As you can see we have added a new function to the product collection sortByReview(), so we need to implement this function. For this we will override the product collection class and add the function sortByReview(). For tutorial on override view this blog article.
The sortByReview function is given below

public function sortByReview($dir){
    	$table = $this->getTable('review/review');
    	$entity_code_id = Mage::getModel('review/review')->getEntityIdByCode(Mage_Rating_Model_Rating::ENTITY_PRODUCT_CODE);
    	$cond = $this->getConnection()->quoteInto('t2.entity_pk_value = e.entity_id and ','').
    	$this->getConnection()->quoteInto('t2.entity_id = ? ',$entity_code_id);
    	$this->getSelect()->joinLeft(array('t2'=>$table), $cond,array('review' => new Zend_Db_Expr('count(review_id)')))
    	->group('e.entity_id')->order("review $dir");
    }