Magento – order sub categories alphabetically

category-tree

I have spent hours searching forums and trying several methods but cant get anywhere. does anyone know how to order all sub categories in magento to display alphabetically front end A-Z?

Best Answer

if you take a look on the template file for layered navigation (catalog\layer\view.phtml), you can see that, layered navigation filtering is carried out by this call

<?php $_filters = $this->getFilters() ?>

So take a look on getFilters() method in Mage_Catalog_Block_Layer_View block class.

public function getFilters()
{
    $filters = array();
    if ($categoryFilter = $this->_getCategoryFilter()) {
        $filters[] = $categoryFilter;
    }

    $filterableAttributes = $this->_getFilterableAttributes();
    foreach ($filterableAttributes as $attribute) {
        $filters[] = $this->getChild($attribute->getAttributeCode() . '_filter');
    }

    return $filters;
}

Here you can see that, the method returns an array $filters, which is get filled in two sections. First the array get filled by category filters then it is filled by custom attribute filters. This means that, category filters are available in layered navigation by default

If we dig more and more, we will reach in the model class Mage_Catalog_Model_Layer_Filter_Category, where the actual category filters for layered navigations are carried out. The method that we interested here is _getItemsData()

 protected function _getItemsData()
{
    $key = $this->getLayer()->getStateKey().'_SUBCATEGORIES';
    $data = $this->getLayer()->getAggregator()->getCacheData($key);

    if ($data === null) {
        $categoty   = $this->getCategory();
        /** @var $categoty Mage_Catalog_Model_Categeory */
        $categories = $categoty->getChildrenCategories();

        $this->getLayer()->getProductCollection()
            ->addCountToCategories($categories);

        $data = array();
        foreach ($categories as $category) {
            if ($category->getIsActive() && $category->getProductCount()) {
                $data[] = array(
                    'label' => Mage::helper('core')->escapeHtml($category->getName()),
                    'value' => $category->getId(),
                    'count' => $category->getProductCount(),
                );
            }
        }
        $tags = $this->getLayer()->getStateTags();
        $this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
    }
    return $data;
}

This is where category filters are preparing. The heart of this function is foreach. It uses that loop to load the $data variable(holds an array) which is then return to layered navigation filter. You can again see that, $data holds only 3 parameter of a specific category. They are label,value and children count. So the category section that present in layered navigation actually built up with these three values.

So this is the place that we need to work. By default categories are loading in random, means no filtering is applying there. What we need to do is, we need to sort the $data variable in ascending order.

So rewrite this model as like this.

 protected function _getItemsData()
{
    $key = $this->getLayer()->getStateKey().'_SUBCATEGORIES';
    $data = $this->getLayer()->getAggregator()->getCacheData($key);

    if ($data === null) {
        $categoty   = $this->getCategory();
        /** @var $categoty Mage_Catalog_Model_Categeory */
        $categories = $categoty->getChildrenCategories();

        $this->getLayer()->getProductCollection()
            ->addCountToCategories($categories);

        $data = array();

        foreach ($categories as $category) {
            if ($category->getIsActive() && $category->getProductCount()) {
                $data[] = array(
                    'label' => Mage::helper('core')->escapeHtml($category->getName()),
                    'value' => $category->getId(),
                    'count' => $category->getProductCount(),
                );
            }
        }

        function cmp($a, $b)
        {
            return strcmp($a["label"], $b["label"]);
        }
        usort($data, "cmp");
        $tags = $this->getLayer()->getStateTags();
        $this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
    }
    return $data;
}

This is the additional part that do the job for us

        function cmp($a, $b)
        {
            return strcmp($a["label"], $b["label"]);
        }
        usort($data, "cmp");

This will filter categories in ascending order for layered navigation.

Note:: You are lucky, I have this in extension format. You can use it. This is the github page that holds that extension. Feel free to use it

Related Topic