Sort Magento Collection AFTER Download

Magento collection sorting functions (for example, Mage_Eav_Model_Entity_Collection_Abstract::addAttributeToSort ) work by adding an ORDER BY to the SQL select statement. However, there are times when the collection is already loaded, and you need to sort the collection.

Of course, it is possible to use the toArray($fields) function, and then the PHP array sorting functions (both native and user-defined), however this is a bit awkward. It also means that the objects in the collection are converted to "dumb" value strings without magic getters / setters, which can be / implemented using algorithms, etc.

I am wondering if there are more elegant / Magento -esque collection sorting methods.

Thanks,
Jonathan

+6
source share
5 answers

Another solution that works:

 class Aligent_Navigation_Block_Dropdown extends Mage_Catalog_Block_Product_List { public function getProductsByShortDesc(){ $data = $this->getLoadedProductCollection()->getItems(); //an array of objects usort($data,array('Aligent_Navigation_Block_Dropdown','sortByShortDesc')); return $data; } public static function sortByShortDesc($a, $b) { if($a->getShortDescription() == $b->getShortDescription()){ return 0 ; } return ($a->getShortDescription() < $b->getShortDescription()) ? -1 : 1; } } 
+2
source

There is no right way to do this. But I think this is possible using Reflection. You can get the $ _items property of the collection object, sort them and set them back into the collection.

 function sortCollection(Varien_Data_Collection $collection, callable $sorter) { $collectionReflection = new ReflectionObject($collection); $itemsPropertyReflection = $collectionReflection->getProperty('_items'); $itemsPropertyReflection->setAccessible(true); // Make it accessible $collectionItems = $itemsPropertyReflection->getValue($collection); usort($collectionItems, $sorter); $itemsPropertyReflection->setValue($collection, $collectionItems); $itemsPropertyReflection->setAccessible(false); // Return restriction back return $collection; } 
+12
source

Here is a tip; The clear collection method disables its load flag, it allows you to change the sort or filters and start a new query.

I accidentally discovered this when downloading only custom products .

+4
source

The @Ivan Chepurnyi method worked, but it returns a ReflectionObject, in my case I need Varien_Data_Collection.
Here is what I did instead

 $collectionItems = $collection->getItems(); usort($collectionItems, array($this, '_sortItems')); $newCollection = new Varien_Data_Collection(); foreach ($collectionItems as $item) { $newCollection->addItem($item); } var_dump($newCollection); 

And in this case, the sorting method

 public function _sortItems($a, $b) { $columnId = "your_column_that_you_need_to_sort"; $dir = "desc"; $al = strtolower($a->getData($columnId)); $bl = strtolower($b->getData($columnId)); if ($al == $bl) { return 0; } if ($dir == 'asc') { return ($al < $bl) ? -1 : 1; } else { return ($al > $bl) ? -1 : 1; } } 
+1
source

The above solution will work fine, but it is LOT slower and more intensive than adding sorting to the request itself.

If you have a large collection, you will use a huge amount of memory, since you need to load an object (or objects) for each result and save them all.

Using the Magento collection will only load one row at a time from the database, which will be much more efficient than the above solution :-)

0
source

All Articles