Magento – List categories alphabetically

categorycategory-tree

I need to have the categories list display alphabetically by default. I have a large number of categories/sub-categories and list them in various ways around the site. How can I always have the categories list alphabetically?

Thank you

Best Answer

There may be lot of ways to achieve this. In my method I am going to rewrite a core model file, so that it will set the layered navigation filter array with sorted category array.

What is layered navigation filter array ? Sounds confusing. Then I will explain it little bit.

app/design/frontend/<your_package>/<your_theme>/template/catalog/layer/view.phtml is the starting point of layered navigation blocks. In that file you can see that, it invokes below method

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

to show the layered navigation content. This method is defined in Mage_Catalog_Block_Layer_View class and the file is in the location app/code/core/Mage/Catalog/Block/Layer/View.php. Let us analyze this method.

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

I called $filters as layered navigation filter array. From above code you can see that category filtering and attribute filtering are storing into this array seperately.

We are interested in category filtering. The main actions of category filtering happens in Model file. The model file that we interested in is app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php. Take a look on _getItemsData() in that file.

<?php
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;
    }

From the above code, you can see that $data is a multidimensional array that holds an UNSORTED arrays as its sub-arrays. We need to sort them in order to achieve our goal. In order to do that, I am gonna create a small module that overwrite this model and sort $data array.

  1. config.xml

Location :app/etc/code/local/Programmerrkt/Layerednav/etc/config.xml

 <config>
    <modules>
        <Programmerrkt_Layerednav>
            <version>0.1.0</version>
        </Programmerrkt_Layerednav>
    </modules>
    <global>
        <models>
            <catalog>
                <rewrite>
                    <!-- Model rewrite-->
                    <layer_filter_category>Programmerrkt_Layerednav_Model_Layer_Filter_Category</layer_filter_category>
                </rewrite>
            </catalog>
        </models>
    </global>
</config>

config.xml tells to magento that I am going to overwrite the core model Mage_Catalog_Model_Layer_Filter_Category.

  1. Programmerrkt_Layerednav.xml

Location :app/etc/modules/Programmerrkt_Layerednav.xml

 <config>
    <modules>
        <Programmerrkt_Layerednav>
            <active>true</active>
            <codePool>local</codePool>
        </Programmerrkt_Layerednav>
    </modules>
</config>

This file activates our module.

  1. Category.php

Location :app/etc/code/local/Programmerrkt/Layerednav/Model/Layer/Filter/Category.php

<?php

class Programmerrkt_Layerednav_Model_Layer_Filter_Category extends Mage_Catalog_Model_Layer_Filter_Category {
    /**
     * Get data array for building category filter items
     *
     * @return array
     */
    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;
    }
}

Section that sorts $data array is

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

Thats it. Clear cache and then load your pages.

Note: This is for sorting category listing in layered navigation

Thanks