Tips & Tricks
-
Dec 15
2012 -
Sort product list by rating
I was trying to make my list sort by product rating (review), and I used this Fontis article as a base, but it didn’t work for me, because rating_summary field was being overwritten later on by review observer, who injected it’s own object in that array key, and besides that, review observer loaded the collection, thereby effectively making it impossible to all other observers to modify collection.
To make it work, I first created an observer. Observer would normally be hooked to catalog_block_product_list_collection. However since Mage_Review_Model_Observer takes presedence to local observers, and loads the collection, that would not work. So, since I don’t know how to sort event observers (I don’t think it’s possible, but if you do know how, please share), I had to overwrite Mage_Review_Model_Observer (lesser evil than to overwrite List.php) and overwrite catalogBlockProductCollectionBeforeToHtml with my own:
select allpublic function catalogBlockProductCollectionBeforeToHtml(Varien_Event_Observer $observer) { $productCollection = $observer->getEvent()->getCollection(); Mage::dispatchEvent('catalog_block_product_list_collection_before_review', array( 'collection' => $productCollection )); if ($productCollection instanceof Varien_Data_Collection) { $productCollection->load(); Mage::getModel('review/review')->appendSummary($productCollection); } return $this; }
and throw a new event here, catalog_block_product_list_collection_before_review, to allow all the other observers to modify the collection before Review observer loads it. So then, I hooked my observer to the new event, and implemented Fontis code, with one change. I had to change the field alias, at the start of the expression, so that it would not get overwritten, or PHP would not throw a key exists warning/notice.
(this is a reference to Fontis article code) Instead of:
select all$this->_productCollection ->joinField('rating_summary', 'review_entity_summary', 'rating_summary', 'entity_pk_value=entity_id', array('entity_type'=>1, 'store_id'=> Mage::app()->getStore()->getId()), 'left' );
I used:
select all$this->_productCollection ->joinField('rating_score', 'review_entity_summary', 'rating_summary', 'entity_pk_value=entity_id', array('entity_type'=>1, 'store_id'=> Mage::app()->getStore()->getId()), 'left' );
So, to summarize, I overwrote Mage_Review_Model_Observer, and placed a new event before collection was loaded. I hooked on to that event in my own observer, that incorporated modified fontis code, and changed the collection. After that, Review observer did it’s own stuff, and collection was fine. Don’t forget to do the Config.php part as well, as outlined in Fontis article, but use rating_score instead of rating_summary.




2 Responses to Sort product list by rating
Hi,
I copied the following files from from core to local folder and made changes as suggested by fontis article.
app/code/local/Mage/Catalog/Block/Product/List.php
app/code/local/Mage/Catalog/Model/Config.php
It didnt work.
Then i copied the file
app\code\core\Mage\Review\Model\Observer.php
to
app\code\local\Mage\Review\Model\Observer.php
and overwrote the method “catalogBlockProductCollectionBeforeToHtml” with your modified method and changed “rating_summary” to “rating_score” in both config.php & List.php
but i am still getting “Joined field with this alias is already declared” error.
Am i missing something?
Any help is appreciated
You will get this error when you have more than one listing on a page. You need to remove toolbars. I had three product listing blocks on my homepage. I solved this by giving my listing template files a new Block class Netismine_Various_Block_Catalog_List_Homepage that extends Mage_Catalog_Block_Product_List and overwriting _beforeToHtml() :