按子类别,属性和产品名称对集合进行排序 [英] sorting collections by subcategory, an attribute and by productname

查看:87
本文介绍了按子类别,属性和产品名称对集合进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经研究问题了几个小时了,看来我找不到找到使上述排序起作用的方法.

I been working on a problem for hours now and it seems I can not find a way to get the above sorting to work.

在magento项目中(相对于magento而言,它相对较新),我必须首先按子类别对集合进行排序,然后对属性进行排序,最后对产品名称进行排序. is Anchor设置为适用于所有类别,因此父类别也显示子类别产品.

In an magento project (im relatively new to magento) I have to sort the collection first by subcategory, then an attribute and last by the product name. is Anchor is set to ture with all categories, so parent categories also show subcategory products.

我想到了使用ReflectionObjectusort() PHP函数以及比较器函数的想法,像这样:

I came across an idea of using the ReflectionObject using the usort() PHP function with an comparator function, like this:

private static function cmp($a, $b) {
    $a_product_geschmack = Mage::getModel('catalog/product')
       ->load($a->getId())->getAttributeText('ws_geschmack');
    $b_product_geschmack = Mage::getModel('catalog/product')
       ->load($b->getId())->getAttributeText('ws_geschmack');

    $r = strcmp(get_category($a), get_category($b));
    if ($r != 0)
       return $r;

    $r = strcmp($a_product_geschmack, $b_product_geschmack);
    if ($r != 0)
       return $r;

    return strcmp($a->getName(), $b->getName());
}

获取子类别的帮助函数如下:

The helper function to get the subcategory looks like this:

function get_category($product) {
    $categoryModel = Mage::getModel( 'catalog/category' );
    // Get Array of Category Id's with Last as First (Reversed)
    $_categories = array_reverse( $product->getCategoryIds() );
    // Get Parent Category Id
    $_parentId = $categoryModel->load($_categories[0])->getParentId();
    // Load Parent Category
    $_category = $categoryModel->load($_parentId);

    return $_category->getName();
}

Mage_Catalog_Block_Product_List_getProductCollection()方法中将上述比较器与usort和ReflectionObject一起使用:

Using the above comparator with usort and the ReflectionObject in the _getProductCollection() method of Mage_Catalog_Block_Product_List:

// ...
$collection = $this->_productCollection;

$collectionReflection = new ReflectionObject($collection);
$itemsPropertyReflection = $collectionReflection->getProperty('_items');
$itemsPropertyReflection->setAccessible(true); // Make it accessible

$collectionItems = $itemsPropertyReflection->getValue($collection);

usort($collectionItems, array('Mage_Catalog_Block_Product_List', 'cmp'));
$itemsPropertyReflection->setValue($collectionReflection, $collectionItems);
$itemsPropertyReflection->setAccessible(false); // Return restriction back

$this->_productCollection = $collection;
// ...

以上所有内容均在Mage_Catalog_Block_Product_List类中设置为测试(以查看其是否有效).为节省起见,我用Toolbar.php

All above I set up as a test (to see if it is working) in the Mage_Catalog_Block_Product_List class. For savety I commented out the default sorting setting with setOrder in Toolbar.php

上述代码位于 https://magento.stackexchange. com/questions/5438/on-search-result-group-products-by-category ,并且看起来很有希望(即使这比OO更具攻击性).

Above code I found at https://magento.stackexchange.com/questions/5438/on-search-result-group-products-by-category and it seemed promising (even if this is more a hack than OO).

当我打印$collectionItems时,顺序是预期的.在前端,它不是预期的,例如,属性ws_geschmack未排序,子类别也未正确"排序.

When I print $collectionItems the order is as expected. In the Frontend it is not as expected, for example the attribute ws_geschmack is not sorted and also the subcategory is not "properly" sorted.

我也问自己,将$collection传递回_productCollection成员的方式是否可行(就像在stackexchange答案中的示例代码中一样).我发现,在ReflectionObject类中还有一个名为setValue的方法,但也不起作用.

I also ask myself if the way passing back $collection to the _productCollection member is the way to go (as it is in the sample code found in the stackexchange answer). I found out, there is also a method called setValue in the ReflectionObject class, but also does not work.

好吧,如果子类别是一个属性,那么问题就不是真正的问题了,在这种情况下,我可以只使用setOrder和一系列字段按ASC顺序进行排序.

Well, the problem would be not a real problem, if the subcategory would be an attribute, in this case I could just use the setOrder with an array of fields to sort in ASC order.

此外,后端中类别的顺序(如果我按字母顺序对其进行排序)似乎没有任何作用.如果可以,我可以删除该子类别的排序.

Also the order of the categories in the backend (if I order them alphabetically) seem to have no effect. If this would work, I could drop the sorting for the subcategory.

排序必须在类别产品列表和搜索结果列表中起作用,后者并不是很重要,但是类别浏览很重要.

The sorting has to work in the category product listing and in the search results list, the latter is not so important, but the category browsing is.

另一个问题与我的问题类似( https://magento.stackexchange.com/questions/2889/sorting-product-list-by-more-than-one-attribute ),但是那个家伙只有属性,可以使用setOrder调用解决数组.

Another questions is alo similar to mine (https://magento.stackexchange.com/questions/2889/sorting-product-list-by-more-than-one-attribute), but that guy had only attributes and that can be solved with an setOrder Call using an array.

所以我没主意.有人知道如何解决此问题吗?任何帮助是极大的赞赏!

So I am out of ideas. Anybody has an idea how to get this issue solved? Any help is greatly appreciated!

我正在为此项目使用magento 1.7.0.2版.

I am using magento version 1.7.0.2 for this project.

更新

只是为了澄清我要寻找的内容:我实现了完全满足我需要的此迭代代码.它首先获取当前类别的子类别,然后查询这些子类别中的所有产品.结果是类别的排序列表,产品结果/子列表通过属性ws_geschmackname排序:

Just to clarify what I am looking for: I implemented this iterative code which does exactly what I need. It first gets the sub-categories of the current category, then it queries all the products in these subcategories. The result is sorted list of categories, and the product results / sublists are sorted by the attribute ws_geschmack and name:

$categories = Mage::getModel('catalog/category')->getCollection()
    ->addAttributeToSelect('name')
    ->addFieldToFilter('parent_id',
        array(
            'eq' => Mage::getModel('catalog/layer')->getCurrentCategory()->getId()))
    ->addFieldToFilter('include_in_menu',array('eq' => '1'))
    ->addFieldToFilter('is_active', array('eq' => '1'))
    ->addAttributeToFilter('is_active', 1)
    ->addAttributeToSort('name', 'asc');

foreach($categories as $category) {
    // Check if there are products for sale in this category
    if (Mage::getModel('catalog/category')->load($category->getId())
        ->getProductCollection()
        ->addAttributeToSelect('entity_id')
        ->addAttributeToFilter('status', 1)
        ->addAttributeToFilter('visibility', 4)
        ->count() == 0) continue;


    print "-> " . $category->getId() .': '. $category->getName() . "<br />";

    // Get all child categories below this current category
    $_subcategory_ids = get_categories(Mage::getModel('catalog/category')->getCategories($category->getId()));

    // Build 'finset' query for category_id filter
    $_subcategory_finset_ids = array_map(
        function($elem) {
            return array('finset' => $elem);
        },
    $_subcategory_ids);

    $_products = Mage::getModel('catalog/product')
        ->getCollection()
        ->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id = entity_id', null, 'left')
        ->addAttributeToSelect('*')
        ->addAttributeToFilter('status', 1)
        ->addAttributeToFilter('visibility', 4)
        ->addAttributeToFilter('is_saleable', array('like' => '1'))
        ->addAttributeToFilter('category_id', $_subcategory_finset_ids)
        ->addAttributeToSort('ws_geschmack', 'ASC')
        ->addAttributeToSort('name', 'ASC');

    if ($_products->count() != 0) {
        foreach ($_products as $_product) {
            $prod = Mage::getModel('catalog/product')->load($_product->getId());
            echo $prod->getName() . ": " . $prod->getAttributeText('ws_geschmack') . "<br />";
        }
    }
}

这只是一个演示代码,我不能按原样使用它.例如,我需要作为getLoadedProductCollection()的返回值的所有内容.我想实现该功能绝非易事.

This is just a demo code, I can not use it as is. All that I would need as the return value from getLoadedProductCollection() for example. I guess it will be no easy task to implement that functionality.

推荐答案

我不确定这是否是预期的结果,但是根据您的标准,以下内容是否将按您需要的方式设置集合? /p>

I'm not sure if this is the expected result, but given your criteria, will the following below set the collection in the way you need it to?

$products = Mage::getModel( 'catalog/product' )
    ->getCollection()
    ->addAttributeToSelect( '*' )
    ->addFieldToFilter( 'status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED )
    ->addFieldToFilter( 'visibility', Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH );
    ->addAttributeToFilter( 'category_id', array( 'in' => array( 'finset' => '[CATEGORY_ID_HERE]' ) ) );
    ->addAttributeToSort( 'category_id', ASC )
    ->addAttributeToSort( 'ws_geschmack', ASC )
    ->addAttributeToSort( 'name', ASC );

您可以使用类似的方法来缩小收藏范围并简化事情.还知道,如果您要自定义内置的产品收集方法,则前端的分类器可能会修改您的前端,因此您可能要确保它不会影响前端.

You can use similar methods to narrow down your collection and simplify things. Also know that if you are customizing the built in product collection methods that the sorter on the front end may be modifying your front-end, so you may want to make sure it's not affecting it.

这篇关于按子类别,属性和产品名称对集合进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆