3

I want to sort catalog products by name in natural order. In order to achieve it i created a custom module and overwrote Mage_Catalog_Block_Product_List_Toolbar.

   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() == 'name') {           
            //i'm assigning the custom sorted collection
            $this->_collection = $this->_naturalsort($this->_collection);
            //printing the collection to check whether it's in proper order
             $this->_test($this->_collection);
        }else if ($this->getCurrentOrder()) {
            $this->_collection->setOrder($this->getCurrentOrder(), $this->getCurrentDirection());
        }        
        return $this;
    }

    protected function _naturalsort($collection){
        $prodarr = $collection->exportToArray(); 
        usort($prodarr, function($a, $b) {          
            return strnatcmp($a['name'], $b['name']);
        });
        $collectionsorted = new Varien_Data_Collection();
        foreach($prodarr as $item)
        {
            $varienObject = new Varien_Object();
            $varienObject->setData($item);
            $collectionsorted->addItem($varienObject);

        }         
        return $collectionsorted;
    }
    protected function _test($collection){
       foreach($collection as $item2)
        {
            Mage::log($item2['name']);
        }        
    }

When logging the collection using my _test method the products are in correct order. Still it doesn't affect the frontend view. The frontend displays a non sorted collection. What am i doing wrong?

1 Answer 1

3

You replaced the collection in the toolbar block, but the list block which is used to display the products still contains the original collection.

Since the toolbar adds the sort order, changing the order there seems like the right choice. But you don't have access to the list block at that point, so another change will be necessary after the call to $toolbar->setCollection()

There is an event, catalog_block_product_list_collection but unfortunately the only parameter is the collection itself, so you can modify it, but not replace it.

My suggestion is to rewrite Mage_Catalog_Block_Product_List::_beforeToHtml() like this:

protected function _beforeToHtml()
{
    parent::_beforeToHtml();
    if ($this->getCurrentOrder() == 'name')
    {
        $this->_collection = $this->_naturalsort($this->_collection);
    }
}

and move _naturalsort() there. The rewrite of Mage_Catalog_Block_Product_List_Toolbar::setCollection() is not necessary anymore then.

7
  • Thanks for the answer. I will try this out and mark it as correct Jun 13, 2016 at 0:39
  • I rewrote Mage_Catalog_Block_Product_List::_beforeToHtml() like above. But unfortunately $this->getCurrentOrder() is empty Jun 13, 2016 at 16:19
  • Use $this->getToolbar()->getCurrentOrder() instead Jun 13, 2016 at 16:24
  • I get Fatal error: Call to a member function getCurrentOrder() on a non-object Jun 13, 2016 at 16:26
  • Ah, sorry, it's $this->getChild('toolbar')->getCurrentOrder () Jun 13, 2016 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.