Get Categories and Its Sub Categories

The question:

Under Default Category I have created another category called Inventory under which I have other categories and sub-categories. I don’t want to display Inventory category but all the categories and sub-categories that are under it in the below format so how do I accomplish it in .phtml file?

Category 1
 Sub Category 1 of Category 1
 Sub Category 2 of Category 1
 Sub Category 3 of Category 1
 etc.

Category 2
 Sub Category 1 of Category 2
 Sub Category 2 of Category 2
 Sub Category 3 of Category 2
 etc.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

<?php 
$_helper = Mage::helper('catalog/category');
$_categories = $_helper->getStoreCategories();
if (count($_categories) > 0){
    foreach($_categories as $_category){
        $_category = Mage::getModel('catalog/category')->load($_category->getId());
        $_subcategories = $_category->getChildrenCategories();
        if (count($_subcategories) > 0){
            echo $_category->getName();
            echo $_category->getId();      
            foreach($_subcategories as $_subcategory){
                 echo $_subcategory->getName();
                 echo $_subcategory->getId();
            }
        }
    }
}
?>

To only one category

<?php 
$category = Mage::getModel('catalog/category')->load(4);
$subcategories = $category->getChildrenCategories();
if (count($subcategories) > 0){
    echo $category->getName();
    foreach($subcategories as $subcategory){
         echo $subcategory->getName();
    }
}
?>

Method 2

Here are two recursive functions: one outputs the categories as a DOM tree, and the other returns a descriptive associative array.

// Make this work outside of magento, for development purposes
require_once("app/Mage.php");
umask(0);
Mage::app();
// End development purposes code

// for getting data:
function getChildCategories($category, $isFirst = false) {

        // If this is the first invocation, we just want to iterate through the top level categories, otherwise fetch the children
        $children = $isFirst ? $category : $category->getChildren();

        // For each category, fetch its children recursively
        foreach ($children as $child) {
                $_categories[] = [ "name" => $child->getName(), "id" => $child->getId(), "children" => getChildCategories($child) ];
        }

        // Return our tree
        return $_categories;
};

// for rendering:
function renderCategoriesTree($category, $isFirst = false) {

        // If this is the first invocation, we just want to iterate through the top level categories, otherwise fetch the children
        $children = $isFirst ? $category : $category->getChildren();
        echo "<ul>";
        // For each category, fetch its children recursively
        foreach ($children as $child) {
                echo "<li>"; echo $child->getName(); echo "</li>";
                renderCategoriesTree($child);
        }
        echo "</ul>";
}


// Example Usage:
$_categories = Mage::helper('catalog/category')->getStoreCategories();

// var_dump this to see an associative array of all categories
$categories = getChildCategories($_categories, true);

// Run this to echo out a DOM
renderCategoriesTree($_categories, true);

Method 3

I am using Magento 1.9.2.1 and attempted Dexxtz’s solution. I found that not all the necessary information was present for me to continue. For example, the img Url returned nothing. In my case, I was building a custom navigation with category images.

After debugging using:

echo "<pre>"; var_dump(Zend_Debug::dump($subcategory->getData())); echo "</pre>"; die;

I found the image was not even being returned at all. In my case, I found that getCollection() better suited my needs:

    $_cat = Mage::getModel('catalog/category')->load($id);
    if (isset($_cat) && !empty($_cat) && is_object($_cat)) {
        // Create category collection for children
        $childrenCollection = $_cat->getCollection();
        // Only get child categories of parent cat
        $childrenCollection->addIdFilter($_cat->getChildren());
        // Only get active categories
        $childrenCollection->addAttributeToFilter('is_active', 1);
        // Add base attributes
        $childrenCollection->addAttributeToSelect('url_key')
                ->addAttributeToSelect('name')
                ->addAttributeToSelect('all_children')
                ->addAttributeToSelect('is_anchor')
                ->setOrder('position', Varien_Db_Select::SQL_ASC)
                ->joinUrlRewrite();
        // Add Image 
        $childrenCollection->addAttributeToSelect('image');
        if (count($childrenCollection) > 0) {
            foreach($childrenCollection as $subcat) {
                if ($subcat->getIsActive()) {
                    $subcatName = $subcat->getName();
                    // Rest of code here    
                }
            }
        }
    }

Hope this helps others in my position.

Method 4

This will return a map between [categoryID] => [categoryName] for all categories and sub-categories with one method call. (not sure about the performance, if anyone knows please tell me)

I tested in v1.9.3.2

function getCategoryNames()
{
  $allCategories = Mage::getModel('catalog/category')->getCollection()->addAttributeToSelect(['name']);
  foreach($allCategories as $cat) {
    $cats[$cat->getId()] = $cat->getName();
  }
  return $cats;
}

I believe you can add other data fields within addAttributeToSelect(…) if you need.

Method 5

Gets all cats and sub cats of those cats 😀

require_once("app/Mage.php");
umask(0);
Mage::app();

$_helper = Mage::helper('catalog/category');
$_categories = $_helper->getStoreCategories();

$cats = array();

function getCats($_categories)
{
    global $cats;
    foreach ($_categories as $_category) {
        if($_category->getIsActive()) {
            $cats[$_category->getId()] = $_category->getName();
            $childCats = $_category->getChildrenCategories();
            if (count($childCats) > 0) getLowestCats($childCats);
        }
    }
}
getCats($_categories);

ksort($cats);
foreach ($cats as $k => $aCat) {
    echo "(".$k.") ".$aCat."<br>n";
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment