【发布时间】: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_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() 的返回值。我想实现该功能并非易事。
【问题讨论】:
标签: php magento sorting collections usort