繁体   English   中英

在加载后对Magento系列进行排序

[英]sort Magento collection AFTER load

Magento集合排序函数(例如Mage_Eav_Model_Entity_Collection_Abstract::addAttributeToSort )通过向SQL select语句添加ORDER BY子句来工作。 但是,有时候已经加载了一个集合,并且有必要对集合进行排序。

当然可以使用toArray($fields)函数,然后使用PHP数组排序函数(本机或用户定义),但这有点笨拙。 这也意味着集合中的对象被转换为“哑”值的行,而没有可以/可以用算法等实现的魔法getter / setter。

我想知道是否有更优雅/ Magento-esque方法对系列进行排序。

谢谢,
乔纳森

没有正确的方法。 但我认为使用反射是可能的。 您可以检索集合对象的$ _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;
}

这是一个提示; 集合的clear方法clear它的加载标志,它允许您更改排序或过滤器并运行新查询。

我在回答仅加载可配置产品时偶然发现了它。

@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;
    }
}

另一种解决方案:

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;
}
}

上面的解决方案可以正常工作,但它比将查询添加到查询本身要慢得多,也更加密集。

如果你有一个大型集合,你将需要使用大量内存,因为你需要在每个结果前加载一个或多个对象并将它们全部存储起来。

使用集合Magento将只从数据库一次加载一行,这将比上述解决方案更有效:-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM