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