0

我已经解决了几个小时的问题,似乎我找不到让上述排序工作的方法。

在一个magento项目中(我对magento比较陌生)我必须首先按子类别对集合进行排序,然后是属性,最后是产品名称。is Anchor设置为 ture 与所有类别,因此父类别也显示子类别产品。

我遇到了将PHP 函数与比较器函数一起ReflectionObject使用的想法,如下所示:usort()

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

获取子类别的辅助函数如下所示:

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

_getProductCollection()在以下方法中使用上述比较器与 usort 和 ReflectionObject 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_ListsetOrder为了安全起见,我用in注释掉了默认排序设置Toolbar.php

我在https://magento.stackexchange.com/questions/5438/on-search-result-group-products-by-category找到的以上代码看起来很有希望(即使这比 OO 更像是一个 hack)。

当我打印$collectionItems订单时,正如预期的那样。在前端,它与预期不符,例如属性ws_geschmack未排序,子类别也未“正确”排序。

我还问自己,传回$collection_productCollection成员的方式是否正确(就像在 stackexchange 答案中的示例代码中一样)。我发现,类中还有一个方法调用setValueReflectionObject但也不起作用。

好吧,如果子类别是一个属性,那么问题就不是真正的问题,在这种情况下,我可以将setOrder与字段数组一起使用以按 ASC 顺序排序。

此外,后端类别的顺序(如果我按字母顺序排列)似乎没有效果。如果这可行,我可以放弃子类别的排序。

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

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

所以我没有想法。有人知道如何解决这个问题吗?任何帮助是极大的赞赏!

我正在为这个项目使用 magento 版本 1.7.0.2。

更新

只是为了澄清我在寻找什么:我实现了这个迭代代码,它完全符合我的需要。它首先获取当前类别的子类别,然后查询这些子类别中的所有产品。结果是分类的排序列表,产品结果/子列表按属性ws_geschmack和排序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()。我想实现该功能并非易事。

4

1 回答 1

0

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

$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 );

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

于 2013-09-30T17:14:03.570 回答