First add a dummy attribute called 'discount_percent' and make it "used for sorting" (just as Giuseppe said in the other answer).
It's not important what type it is or what values it has.
it's easier that way. If you don't want to add the attribute you have to rewrite the method Mage_Catalog_Model_Config::getAttributeUsedForSortByArray
to include your attribute. I would rather avoid rewrites as much as possible.
Now you need to tell magento to take a special action when the sorting is done by that attribute.
For this you have to rewrite (I don't know other way) the method Mage_Catalog_Model_Resource_Product_Collection::addAttributeToSort()
You will need a new module for that. let's call it Easylife_Sorting
.
Here are the files.
app/etc/module/Easylife_Sorting.xml
- the declaration file
<?xml version="1.0"?>
<config>
<modules>
<Easylife_Sorting>
<codePool>local</codePool>
<active>true</active>
<depends>
<Mage_Catalog />
</depends>
</Easylife_Sorting>
</modules>
</config>
app/code/local/Easylife/Sorting/etc/config.xml
- the configuration file
<?xml version="1.0"?>
<config>
<modules>
<Easylife_Sorting>
<version>1.0.0</version>
</Easylife_Sorting>
</modules>
<global>
<models>
<catalog_resource>
<rewrite>
<product_collection>Easylife_Sorting_Model_Resource_Product_Collection</product_collection>
</rewrite>
</catalog_resource>
</models>
</global>
</config>
app/code/local/Easylife/Sorting/Model/Resource/Product/Collection.php
- your class override. Here is where the magic happens.
class Easylife_Sorting_Model_Resource_Product_Collection
extends Mage_Catalog_Model_Resource_Product_Collection {
public function addAttributeToSort($attribute, $dir = self::SORT_ORDER_ASC){
//don't screw up the admin sorting
if (Mage::app()->getStore()->getId() == Mage_Core_Model_App::ADMIN_STORE_ID){
return parent::addAttributeToSort($attribute, $dir);
}
if ($attribute == 'discount_percent') {
//determine the discount percent value
$this->addExpressionAttributeToSelect('discount_percent_value', '(({{price}} - final_price) / {{price}})', array('price'));
//sort by the discount percent value
$sortDir = $dir;
//in case you need to reverse the order so when you sort ascending you will see the most discounts first do this:
//if not then remove the if-else statement below.
if ($sortDir == self::SORT_ORDER_ASC) {
$sortDir = self::SORT_ORDER_DESC;
}
else {
$sortDir = self::SORT_ORDER_ASC;
}
$this->getSelect()->order(array('discount_percent_value '.$sortDir));
return $this;
}
//otherwise do nothing special
return parent::addAttributeToSort($attribute, $dir);
}
}
This works for sure for simple/virtual/downloadable products. I have no idea what effect has on configurable/bundle and grouped products.
Create the file
app/code/local/Mage/Catalog/Block/Product/Mostviewed.php
Then add the following code:
class Mage_Catalog_Block_Product_Mostviewed extends Mage_Catalog_Block_Product_Abstract{
public function __construct(){
parent::__construct();
$storeId = Mage::app()->getStore()->getId();
$products = Mage::getResourceModel('reports/product_collection')
->addOrderedQty()
->addAttributeToSelect('*')
->addAttributeToSelect(array('name', 'price', 'small_image'))
->setStoreId($storeId)
->addStoreFilter($storeId)
->addViewsCount();
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($products);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($products);
$products->setPageSize(5)->setCurPage(1);
$this->setProductCollection($products);
} }
After this, create another file:
app/design/frontend/default/YourTheme/template/catalog/product/mostviewed.phtml
with following code:
<?php if (($_products = $this->getProductCollection()) && $_products->getSize()): ?>
<div class=" most_viewed">
<div class="mv_title"><?php echo $this->__('These Products Are Popular Right Now!') ?></div>
<?php $_collectionSize = 5;//count($_products->getItems()); echo $_collectionSize; ?>
<ul class="products-grid" id="products-grid-table">
<?php $i=1; foreach ($_products->getItems() as $_product): ?>
<li id="td_<?php echo $i;?>" <?php if($i%5==0 or $i==$_collectionSize){echo 'class="last"';} ?> >
<div id="cont_<?php echo $i;?>">
<a class="product-image" href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>">
<img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(135); ?>" width="135" height="135" alt="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>" title="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>" />
</a>
<h3 class="product-name"><a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->htmlEscape($_product->getName()) ?>"><?php echo $this->htmlEscape($_product->getName()) ?></a></h3>
<div class="a-center">
<?php if($_product->getRatingSummary()): ?>
<?php echo $this->getReviewsSummaryHtml($_product, 'short') ?>
<?php endif; ?>
<?php echo $this->getPriceHtml($_product, true) ?>
<?php if($_product->isSaleable()): ?>
<button class="button" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')"><span><span><span><?php echo $this->__('Add to Cart') ?></span></span></span></button>
<div class="clear"></div>
<?php else: ?>
<p class="availability"><span class="out-of-stock"><?php echo $this->__('Out of stock') ?></span></p>
<div class="clear"></div>
<?php endif; ?>
<ul class="add-to-links">
<?php if ($this->helper('wishlist')->isAllow()) : ?>
<li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>"><?php echo $this->__('Add to Wishlist') ?></a></li>
<?php endif; ?>
<?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
<li class="last"><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>"><?php echo $this->__('Add to Compare') ?></a></li>
<?php endif; ?>
</ul>
</div>
</div>
</li>
<?php $i++; endforeach; $kol = $_collectionSize; ?>
</ul>
</div>
<?php endif; ?>
Now, to display it, use this code:
{{block type="catalog/product_mostviewed" template="catalog/product/mostviewed.phtml"}}
And there you could see the most viewed products.
If you want, you could display best selling options with these codes:
app/code/local/Mage/Catalog/Block/Product/Bestseller.php
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('*')
->addAttributeToSelect(array('name', 'price', 'small_image'))
->setStoreId($storeId)
->addStoreFilter($storeId)
->setOrder('ordered_qty', 'desc'); // most best sellers on top
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($products);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($products);
$products->setPageSize(3)->setCurPage(1);
$this->setProductCollection($products);
}
}
And
App/design/frontend/default/YourTheme/template/catalog/product/bestseller.phtml
<?php if (($_products = $this->getProductCollection()) && $_products->getSize()): ?>
<div class="page-title">
<h2><?php echo $this->__('Best Seller Products') ?></h2>
</div>
<?php $_collectionSize = count($_products->getItems()) ?>
<table class="products-grid" id="products-grid-table">
<?php $i=1; foreach ($_products->getItems() as $_product): ?>
<?php if ($i%1!==0): ?>
<tr>
<?php endif ?>
<td id="td_<?php echo $i;?>" <?php if($i%3==0 or $i==$_collectionSize){echo 'class="last"';} ?> >
<?php contentBlock('top') ?>
<div id="cont_<?php echo $i;?>">
<h3 class="product-name"><a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->htmlEscape($_product->getName()) ?>"><?php echo $this->htmlEscape($_product->getName()) ?></a></h3>
<a class="product-image" href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>">
<img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(122, 109); ?>" width="122" height="109" alt="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>" title="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>" />
</a>
<div class="a-center">
<?php if($_product->getRatingSummary()): ?>
<?php echo $this->getReviewsSummaryHtml($_product, 'short') ?>
<?php endif; ?>
<?php echo $this->getPriceHtml($_product, true) ?>
<?php if($_product->isSaleable()): ?>
<button class="button" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')"><span><span><span><?php echo $this->__('Add to Cart') ?></span></span></span></button>
<div class="clear"></div>
<?php else: ?>
<p class="availability"><span class="out-of-stock"><?php echo $this->__('Out of stock') ?></span></p>
<div class="clear"></div>
<?php endif; ?>
<ul class="add-to-links">
<?php if ($this->helper('wishlist')->isAllow()) : ?>
<li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>"><?php echo $this->__('Add to Wishlist') ?></a></li>
<?php endif; ?>
<?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
<li class="last"><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>"><?php echo $this->__('Add to Compare') ?></a></li>
<?php endif; ?>
</ul>
<?php if($_product->getevent_date()) {echo $_product->getevent_date();} ?>
</div>
</div>
</td>
<?php if ($i%3==0 or $i==$_collectionSize): ?>
</tr>
<?php endif ?>
<?php $i++; endforeach; $kol = $_collectionSize; ?>
</table>
<?php endif; ?>
And to display the most selling products:
{{block type="catalog/product_bestseller" template="catalog/product/bestseller.phtml"}}
Best Answer
Open your theme /Magento_Catalog/templates/product/list/toolbar/sorter.phtml file and replace your select block with this code below, you may need to copy the magento template file to your theme :