3

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');
  • you might want to check out this question: stackoverflow.com/questions/6456526/… – pzirkind Apr 9 '13 at 21:25
  • Thanks, unfortunately that's for adding it to the dropdown of sortable items. The client just wants it ordered this way by default when the page loads (first the attribute, then SKU). They don't want the sorting toolbar in there. – jron Apr 9 '13 at 21:31
  • ah, thanks for clarifying maybe this would help: magentocommerce.com/boards/viewthread/58598 – pzirkind Apr 9 '13 at 21:42
  • Thanks for doing that, none of those are changing the sorting though. It must be the way I'm pulling in the collection with $_productCollection=$this->getLoadedProductCollection();, but I got that straight from the Base theme product list.phtml. Is there another method that would work using just getCollection()? – jron Apr 10 '13 at 12:27
4

Did you try this

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

Pass an array of attribute inside the setOrder().

  • I did not, thanks for posting that. We ended up going a totally different route, kind of gave up lol. – jron Apr 12 '13 at 16:18
  • 1
    See my additional answer placed, showing a potential bug?? in CE 1.9.2 – ProxiBlue Nov 6 '15 at 8:49
3

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

  • I've added a working solution for Magento 1.9 – Raul Sanchez Feb 24 '16 at 10:40
2

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;
}
1
$_productCollection=$this->getLoadedProductCollection()->clear()->addAttributeToSort('sku', 'ASC');
  • You should be very careful with this. First you fire two querys, second you might get problems because things are cached somewhere in the block – Fabian Blechschmidt Jun 7 '13 at 5:57
  • can i do the same for category_ids? – Yehuda Schwartz Jun 20 '16 at 16:31
  • it doesnt seem to work do i need to somehow select the smallest or largest value for category_ids of each product to sort by? – Yehuda Schwartz Jun 20 '16 at 16:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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