加载后对 Magento 集合进行排序

发布于 2024-11-01 03:09:46 字数 364 浏览 1 评论 0原文

Magento 集合排序函数(例如Mage_Eav_Model_Entity_Collection_Abstract::addAttributeToSort)通过向SQL select 语句添加ORDER BY 子句来工作。然而,有时集合已经被加载,需要对集合进行排序。

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

我想知道是否有更优雅/Magento 式的排序方法集合。

谢谢,
乔纳森

The Magento collection sorting functions (e.g. Mage_Eav_Model_Entity_Collection_Abstract::addAttributeToSort) work by adding an ORDER BY clause to the SQL select statement. However, there are times when a collection has already been loaded and it is necessary to sort the collection.

It is certainly possible to use the toArray($fields) function and then PHP array sorting functions (either native or user-defined), however this is a little clumsy. It also means that the objects in the collection are converted to "dumb" rows of values without magic getters/setters which can/are be implemented with algorithms, etc.

I'm wondering if there are more elegant/Magento-esque methods of sorting the collection.

Thanks,
Jonathan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

晚风撩人 2024-11-08 03:09:46

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

There is no proper way of doing it. But I think it is possible with using of Reflection. You can retrieve $_items property of collection object, sort them and set it back to 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;
}
才能让你更想念 2024-11-08 03:09:46

这里有一个提示;集合的 clear 方法会取消设置其已加载标志,它允许您更改排序或过滤器并运行新查询。

我在回答仅加载可配置产品时无意中发现了它。

Here's a tip; A collection's clear method unsets it's loaded flag, it allows you to change the sort or filters and run the new query.

I accidentally discovered it when answering load only configurable products.

来世叙缘 2024-11-08 03:09:46

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

The method of @Ivan Chepurnyi worked but returns a ReflectionObject object, in my case I needed a 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 case here is 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;
    }
}
つ可否回来 2024-11-08 03:09:46

另一个有效的解决方案:

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

Another solution which 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;
}
}
为人所爱 2024-11-08 03:09:46

上面的解决方案可以很好地工作,但它比将排序添加到查询本身要慢得多且更密集。

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

使用集合 Magento 一次只会从数据库加载一行,这比上面的解决方案要高效得多:-)

The above solution will work fine, but it's a LOT slower and more intensive than adding the sort to the query itself.

If you have a large collection you will use a huge amount of memory as you need to load an object (or objects) fore each result and store them all.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文