Magento集合排序函数(例如Mage_Eav_Model_Entity_Collection_Abstract::addAttributeToSort
)通过向SQL select语句添加ORDER BY
子句来工作。但是,有时候已经加载了一个集合,并且有必要对集合进行排序。
当然可以使用toArray($fields)
函数,然后使用PHP数组排序函数(本机或用户定义),但这有点笨拙。它还意味着集合中的对象被转换为" dumb"没有魔法getter / setter的值行,可以用算法等实现
我想知道是否有更优雅/ Magento式的排序方法。
谢谢,
乔纳森
答案 0 :(得分:12)
没有正确的方法。但我认为使用反射是可能的。您可以检索集合对象的$ _items属性,对它们进行排序并将其设置回集合。
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;
}
答案 1 :(得分:4)
这是一个提示;集合的clear
方法取消设置它的加载标志,它允许您更改排序或过滤器并运行新查询。
我在回答load only configurable products时意外地发现了它。
答案 2 :(得分:2)
另一个有效的解决方案:
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;
}
}
答案 3 :(得分:2)
@Ivan Chepurnyi的方法有效,但返回一个ReflectionObject对象,在我的例子中我需要一个Varien_Data_Collection。
这是我做的事情
$collectionItems = $collection->getItems();
usort($collectionItems, array($this, '_sortItems'));
$newCollection = new Varien_Data_Collection();
foreach ($collectionItems as $item) {
$newCollection->addItem($item);
}
var_dump($newCollection);
如果这里是排序方法
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;
}
}
答案 4 :(得分:0)
上述解决方案可以正常工作,但是比将查询本身添加到查询本身要慢得多,也更加密集。
如果你有一个大型集合,你需要使用大量内存,因为你需要在每个结果前加载一个或多个对象并将它们全部存储起来。
使用集合Magento将一次只从数据库加载一行,这将比上述解决方案更有效: - )