2013-09-30 66 views
0

我一直在解决一个问题几个小时,似乎我找不到一种方法来获得上述排序工作。按子类别,属性和产品名排序集合

在Magento的项目(IM相对较新的Magento)我必须按子类别排序第一的集合,然后由产品名称的属性和最后一个。 is Anchor设置为与所有类别一致,所以父类别也显示子类别产品。

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

我碰到使用ReflectionObject使用usort() PHP函数与比较功能,这样的想法来到

将上述比较器与usort和_getProductCollection()方法中的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_List类。对于savety我注释掉默认的排序与setOrderToolbar.php

上面的代码,我发现在https://magento.stackexchange.com/questions/5438/on-search-result-group-products-by-category设置,它似乎希望的(即使这是比OO黑客攻击)。

当我打印$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()返回的所有值。我想实现这个功能并不容易。

回答

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

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

+0

谢谢你的回答,杰森。我一直在考虑这种方式,它会是最简单的,但是对类别的排序将通过ID而不是表示该ID的实际类别字符串。另外,我认为'addAttributeToFilter'应该对所有类别和子类别ID(都是''anchor'ed!')执行'OR'操作,这是可能的,而不是问题。但在这里,主要问题仍然没有解决,因为它按数字ID排序。 –