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

Php 按子类别、属性和产品名称对集合进行排序,php,magento,sorting,collections,usort,Php,Magento,Sorting,Collections,Usort,我已经为一个问题工作了好几个小时,似乎我找不到一种方法来让上面的排序工作 在一个magento项目中(我对magento比较陌生),我必须先按子类别对集合排序,然后按属性排序,最后按产品名称排序是锚定的在所有类别中都设置为true,因此父类别也显示子类别产品 我想到了使用ReflectionObject将usort()PHP函数与comparator函数结合使用,如下所示: private static function cmp($a, $b) { $a_product_geschmac

我已经为一个问题工作了好几个小时,似乎我找不到一种方法来让上面的排序工作

在一个magento项目中(我对magento比较陌生),我必须先按子类别对集合排序,然后按属性排序,最后按产品名称排序<代码>是锚定的在所有类别中都设置为true,因此父类别也显示子类别产品

我想到了使用
ReflectionObject
usort()
PHP函数与comparator函数结合使用,如下所示:

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();
}
获取子类别的助手函数如下所示:

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\u Catalog\u Block\u Product\u List
\u 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\u Catalog\u Block\u Product\u List
类中设置了一个测试(看看它是否工作)。对于savety,我在
Toolbar.php

在上面的代码中,我发现了它,它看起来很有希望(即使这更像是一个黑客而不是OO)

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

我还问自己,将
$collection
传递回
\u productCollection
成员的方式是否正确(正如stackexchange答案中的示例代码所示)。我发现,
ReflectionObject
类中还有一个名为
setValue
的方法,但也不起作用

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

此外,后端中类别的顺序(如果我按字母顺序排列)似乎没有任何影响。如果这能起作用,我可以删除子类别的排序

分类必须在类别产品列表和搜索结果列表中进行,后者并不重要,但类别浏览是重要的

另一个问题类似于我的(),但那个家伙只有属性,可以通过使用数组调用
setOrder
来解决

所以我没有主意了。有人知道如何解决这个问题吗?非常感谢您的帮助

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

更新

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

$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 />";
        }
    }
}
$categories=Mage::getModel('catalog/categority')->getCollection()
->addAttributeToSelect('名称')
->addFieldToFilter('parent_id',
排列(
'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作为$category){
//检查是否有此类产品可供销售
如果(Mage::getModel('catalog/category')->load($category->getId())
->getProductCollection()
->addAttributeToSelect('entity_id')
->addAttributeToFilter('状态',1)
->addAttributeToFilter('visibility',4)
->count()==0)继续;
打印“->”$category->getId():”.$category->getName().“
”; //获取当前类别下的所有子类别 $\u subcategory\u id=get\u categories(Mage::getModel('catalog/category')->getCategories($category->getId()); //为类别\u id筛选器生成“finset”查询 $\子类别\ finset\ ID=数组\映射( 功能($elem){ 返回数组('finset'=>$elem); }, $\子类别\标识); $\u products=Mage::getModel('目录/产品') ->getCollection() ->joinField('category\u id','category/category\u product','category\u id','product\u id=entity\u id',null,'left') ->addAttributeToSelect(“*”) ->addAttributeToFilter('状态',1) ->addAttributeToFilter('visibility',4) ->addAttributeToFilter('is_saleable',array('like'=>'1')) ->addAttributeToFilter('category\u id',$\u subcategory\u finset\u id) ->addAttributeToSort('ws_geschmack','ASC') ->addAttributeToSort('name','ASC'); 如果($\u产品->计数()!=0){ foreach($\产品作为$\产品){ $prod=Mage::getModel('catalog/product')->load($\u product->getId()); echo$prod->getName()。“:”$prod->getAttributeText('ws_geschmack')。“
”; } } }

这只是一个演示代码,我不能按原样使用。例如,
getLoadedProductCollection()
返回值所需的所有内容。我想实现这一功能并非易事

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

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

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

谢谢您的回答,Jason。我也一直在考虑这种方式,这将是最简单的,但类别的排序将是按ID,而不是按表示此ID的实际类别字符串。此外,我认为