【问题标题】:sorting collections by subcategory, an attribute and by productname按子类别、属性和产品名称对集合进行排序
【发布时间】:2013-10-06 12:43:07
【问题描述】:

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

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

我想到了使用usort() PHP 函数和比较器函数来使用ReflectionObject 的想法,如下所示:

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

Mage_Catalog_Block_Product_List_getProductCollection()方法中使用上面带有usort和ReflectionObject的比较器:

// ...
$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 中用setOrder 注释掉了默认排序设置

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

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

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

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

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

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

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

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

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

更新

只是为了澄清我在寻找什么:我实现了这个迭代代码,它完全符合我的需要。它首先获取当前类别的子类别,然后查询这些子类别中的所有产品。结果为分类排序列表,商品结果/子列表按属性ws_geschmackname排序:

$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() 的返回值。我想实现该功能并非易事。

【问题讨论】:

    标签: php magento sorting collections usort


    【解决方案1】:

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

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

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

    【讨论】:

    • 感谢您的回答,杰森。我也一直在考虑这种方式,这将是最简单的,但类别的排序将按 ID 而不是代表此 ID 的实际类别字符串。另外,我认为addAttributeToFilter 应该对所有类别和子类别 ID 执行“或”运算(都是is anchored!),这是可能的,而不是问题。但同样在这里,主要问题仍未解决,因为它按数字 ID 排序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 2015-12-31
    相关资源
    最近更新 更多