Question

On my category page's normal listing of products, I have it set to sort the products by a custom yes/no attribute in the admin. This works fine, but I also want to sort it by SKU after it's sorted by the attribute. Here's my current code in catalog list.phtml:

$_productCollection=$this->getLoadedProductCollection();
foreach ($_productCollection as $_product):
    // do product stuff here
endforeach;

I've tried adding things like $_productCollection->setOrder('sku', 'ASC');, addOrder, addAttributeToSort, but none of them seem to actually affect the sort order of the products on the page. What am I missing?


Progress from comments following pzirkind's suggestion of https://stackoverflow.com/questions/5673093/sort-magento-collection-after-load :

$_productCollection=$this->getLoadedProductCollection();

$collectionReflection = new ReflectionObject($_productCollection);
$itemsPropertyReflection = $collectionReflection->getProperty('_items');
$itemsPropertyReflection->setAccessible(true); // Make it accessible

$collectionItems = $itemsPropertyReflection->getValue($_productCollection);

usort($collectionItems, $yourSortingCallback);

$itemsPropertyReflection->setValue($collectionItems, $collectionItems);

$itemsPropertyReflection->setAccessible(false);

There's a couple of issues with this, #1 being that I'm not sure how to get $collectionItems back into the collection... this doesn't do it by itself. If I print_r($collectionItems) it is now sorted by SKU, however the other problem is that the order is only for the products on that page, this sorting is NOT done before pagination is performed some how.


In order to get past the first problem, I tried a different approach and this DOES work. However, it's still only sorting by SKU AFTER pagination

$_productCollection=$this->getLoadedProductCollection()->clear()->addAttributeToSort('sku', 'ASC');
Was it helpful?

Solution

Did you try this

$Collection->setOrder(array('attribute1', 'attribute2'), asc);

Pass an array of attribute inside the setOrder().

OTHER TIPS

Placed into/as answer, as comments will not be appropriate. This expand on the accepted answer:

Did I find a bug? magento 1.9.2

If you use the code, as suggested in the accepted answer: $collection->setOrder(array('attribute1', 'attribute2'), asc); you eventually end up on this routine:

Mage_Eav_Model_Entity_Collection_Abstract::setOrder

public function setOrder($attribute, $dir = self::SORT_ORDER_ASC)
    {
        if (is_array($attribute)) {
            foreach ($attribute as $attr) {
                parent::setOrder($attr, $dir);
            }
        }
        return parent::setOrder($attribute, $dir);
    }

as you can clearly see, the array will be dealt with fine, iterated over and pushed to the parent::setOrder method, one attribute at a time.

However, the final line of code then pushes the passed $attribute value (an array) to the parent as well, but the parent Varien_Data_Collection_Db::setOrder expects a string (the attribute_code)

/**
     * Add select order
     *
     * @param   string $field
     * @param   string $direction
     * @return  Varien_Data_Collection_Db
     */
    public function setOrder($field, $direction = self::SORT_ORDER_DESC)
    {
        return $this->_setOrder($field, $direction);
    }

the result would be an exception Warning: Illegal offset type in isset or empty in /vagrant/www/magento/lib/Varien/Data/Collection/Db.php on line 427

Working solution in Magento 1.9

Rewrite Mage_Catalog_Block_Product_List_Toolbar, with following change

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

    $limit = (int)$this->getLimit();
    if ($limit) {
        $this->_collection->setPageSize($limit);
    }
    if ($this->getCurrentOrder()) {
        $this->_collection->setOrder($this->getCurrentOrder(), $this->getCurrentDirection());
    }

    /** 
     * Main order criteria has been set before
     * Following line adds the second order criteria, 
     * in this example last added products 
     */
    $this->_collection->setOrder('entity_id', 'desc');

    return $this;
}
$_productCollection=$this->getLoadedProductCollection()->clear()->addAttributeToSort('sku', 'ASC');
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top