简体   繁体   English

Magento产品集合分页与自定义排序

[英]Magento product collection pagination with custom sort

I'm overriding Mage_Catalog_Block_Product_List 's _getProductCollection by adding: 我通过添加以下内容来覆盖Mage_Catalog_Block_Product_List的_getProductCollection

foreach ($this->_productCollection as $product) {
     $product->setDistance(Mage::helper('myhelper')->getDistance($product));
}

Now I want the collection to be sorted by distance, I tried the following: 现在,我希望按距离对集合进行排序,我尝试了以下操作:

 $this->_productCollection = Mage::helper('myhelper')->sortProductByDist($this->_productCollection);

The helper for sorting is like following (stolen from SO): 排序的帮助程序如下(从SO窃取的):

public function sortProductByDist($products) {

      $sortedCollection = Mage::getSingleton('catalog/layer')
         ->getProductCollection()->addFieldToFilter('entity_id', 0);

      $sortedCollection = $sortedCollection->clear();
      $collectionItems = $products->getItems();
      usort($collectionItems, array($this,'_sortItems'));

      foreach ($collectionItems as $item) {
          $sortedCollection->addItem($item);              
      }
      return $sortedCollection;
}

protected function _sortItems($a, $b) {
        $order = 'asc';
        $al = strtolower($a->getDistance());
        $bl = strtolower($b->getDistance());

        if ($al == $bl) {
            return 0;
        }

        if ($order == 'asc') {
            return ($al < $bl) ? -1 : 1;
        } else {
            return ($al > $bl) ? -1 : 1;
        }
}

The problem is the product collection is no longer paginated when this additional sort is applied. 问题在于,应用此附加排序后,产品集合将不再被分页。

Anyone knows how to fix this? 有人知道如何解决这个问题吗?

You are not doing it the right way, and there are no easy solutions. 您没有以正确的方式进行操作,并且没有简单的解决方案。 You need to use the database to do the sorting. 您需要使用数据库进行排序。

The _productCollection is not an array, it's an object that has references, the query at this point can still be updated, the pagination will be handled by the query to the database. _productCollection不是数组,它是一个具有引用的对象,此时查询仍然可以更新,分页将由查询处理到数据库。

if you do a 如果你做一个

Mage::log((string) $this->_productCollection->getSelect()); 

you will see the query in the logs 您将在日志中看到查询

What you do is to load the products of the current page, add the distance on all products of the page, and create a new collection where you force your items in. So that collection's data is not coming from the database and only contains the elements of the current page. 您要做的是加载当前页面的产品,在该页面的所有产品上添加距离,并在其中添加项以创建一个新集合。因此,集合的数据不是来自数据库,而仅包含元素当前页面的

Sorting using php is a bad idea, because if you have a lot of products it means you need to load them all from the database. 使用php排序不是一个好主意,因为如果您有很多产品,则意味着您需要从数据库中全部加载它们。 That will be slow. 那会很慢。

The solution 解决方案

Calculate distance in the database directly by modifying the query. 通过修改查询直接在数据库中计算距离。

You can edit the select query and do the distance calculation in the database 您可以编辑选择查询并在数据库中进行距离计算

$this->_productCollection
    ->getSelect()
        ->columns("main.distance as distance")

Now you can add a sort on the product collection 现在您可以在产品集合上添加排序

$this->_productCollection->setOrder('distance');

The complicated part will be to write the equivalent of your getDistance method in mysql. 复杂的部分将是在mysql中编写与getDistance方法等效的方法。 In my example I assumed distance was in the database already. 在我的示例中,我假设距离已经在数据库中。

Don't hesitate to print the query at various steps to understand what is going on. 不要犹豫,在各个步骤中打印查询以了解发生了什么。

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

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