Reputation: 55
How do I add custom sort option in Magento. I want to add Best Sellers, Top rated and exclusive in addition to sort by Price. Please help
Upvotes: 4
Views: 7663
Reputation: 365
To sort out pagination issue for custom sorting collection rewrite the resource model of it's collection from
app\code\core\Mage\Catalog\Model\Resource\Product\Collection.phpAnd modify below method from core
protected function _getSelectCountSql($select = null, $resetLeftJoins = true) { $this->_renderFilters(); $countSelect = (is_null($select)) ? $this->_getClearSelect() : $this->_buildClearSelect($select);/*Added to reset count filters for Group*/ if(count($countSelect->getPart(Zend_Db_Select::GROUP)) > 0) { $countSelect->reset(Zend_Db_Select::GROUP); } /*Added to reset count filters for Group*/ $countSelect->columns('COUNT(DISTINCT e.entity_id)'); if ($resetLeftJoins) { $countSelect->resetJoinLeft(); } return $countSelect; }
Above will solve count issue for custom sorting collection.
Upvotes: 0
Reputation: 422
Thanks for your answer, Anuj, that was the best working module I could find so far.
Just add an extra bit to your code in order to solve no pagination caused by 'group by'
Copy '/lib/varien/data/collection/Db.php' To 'local/varien/data/collection/Db.php'.
Change the getSize function to
public function getSize()
{
if (is_null($this->_totalRecords)) {
$sql = $this->getSelectCountSql();
//$this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams); //============================>change behave of fetchOne to fetchAll
//got array of all COUNT(DISTINCT e.entity_id), then sum
$result = $this->getConnection()->fetchAll($sql, $this->_bindParams);
foreach ($result as $row) {//echo'<pre>'; print_r($row);
$this->_totalRecords += reset($row);
}
}
return intval($this->_totalRecords);
}
Hope it could help anyone.
update The filter section need to be updated as well, otherwise just showing 1 item on all filter. and the price filter will not be accurate.
What you need to do it to modify core/mage/catalog/model/layer/filter/attribute.php and price.php
attribute.php getCount() on bottom
$countArr = array();
//print_r($connection->fetchall($select));
foreach ($connection->fetchall($select) as $single)
{
if (isset($countArr[$single['value']]))
{
$countArr[$single['value']] += $single['count'];
}
else
{
$countArr[$single['value']] = $single['count'];
}
}
//print_r($countArr);//exit;
return $countArr;
//return $connection->fetchPairs($select);
Price.php getMaxPrice
$maxPrice = 0;
foreach ($connection->fetchall($select) as $value)
{
if (reset($value) > $maxPrice)
{
$maxPrice = reset($value);
}
}
return $maxPrice;
If you are having the same problem and looking for the question, you will know what I meant. Good luck, spent 8 hours on that best sell function.
Update again,
just found another method to implement using cron to collect best sale data daily saved in a table that includes product_id and calculated base sale figure. then simply left join, without applying 'group by' that means core functions do not need to changed and speed up the whole sorting process. Finally finished! hehe.
Upvotes: 1
Reputation: 11853
For Best Sellers
haneged in code/local/Mage/Catalog/Block/Product/List/Toolbar.php
method setCollection to
public function setCollection($collection) {
parent::setCollection($collection);
if ($this->getCurrentOrder()) {
if($this->getCurrentOrder() == 'saleability') {
$this->getCollection()->getSelect()
->joinLeft('sales_flat_order_item AS sfoi', 'e.entity_id = sfoi.product_id', 'SUM(sfoi.qty_ordered) AS ordered_qty')
->group('e.entity_id')->order('ordered_qty' . $this->getCurrentDirectionReverse());
} else {
$this->getCollection()
->setOrder($this->getCurrentOrder(), $this->getCurrentDirection());
}
}
return $this;
}
After setCollection I added this method:
public function getCurrentDirectionReverse() {
if ($this->getCurrentDirection() == 'asc') {
return 'desc';
} elseif ($this->getCurrentDirection() == 'desc') {
return 'asc';
} else {
return $this->getCurrentDirection();
}
}
And finally I changed mehod setDefaultOrder to
public function setDefaultOrder($field) {
if (isset($this->_availableOrder[$field])) {
$this->_availableOrder = array(
'name' => $this->__('Name'),
'price' => $this->__('Price'),
'position' => $this->__('Position'),
'saleability' => $this->__('Saleability'),
);
$this->_orderField = $field;
}
return $this;
}
for Top rated
http://www.fontis.com.au/blog/magento/sort-products-rating
try above code.
for date added
i am not associate with any of the above link for any work or concern it is just for knowledge purpose and to solve your issue.
hope this will sure help you.
Upvotes: 8