按子类别,属性和产品名称对集合进行排序

时间:2013-09-30 15:17:07

标签: php magento sorting collections usort

我一直在研究一个问题好几个小时,似乎找不到让上述排序工作的方法。

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

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

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()的{​​{1}}方法中使用上述比较器和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; // ... 课程中设置为测试(以查看它是否正常工作)。对于savety,我在Mage_Catalog_Block_Product_List

中注释了setOrder的默认排序设置

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

当我打印Toolbar.php时,订单符合预期。在前端中,它不是预期的,例如,属性$collectionItems未被排序,并且子类别未被“正确”排序。

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

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

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

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

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

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

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

更新

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

1 个答案:

答案 0 :(得分: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 );

您可以使用类似的方法缩小收藏范围并简化操作。还要知道,如果您要自定义内置产品集合方法,前端的分拣机可能正在修改您的前端,那么您可能需要确保它不会影响它。