6

I have two root categories in the left navigation. And it should be like this:

default: (root1 - doesn't appear on the view itself)
  - sub1
  - sub2
  - sub3

default1: (root2 - doesn't appear on the view itself)
  - ssub1
  - ssub2
  - ssub3

To show first root category run this code:

<?php $_menu = $this->renderCategoriesMenuHtml(0, 'level-top') ?>

What about second root category? How to make it appear in frontend?

UPDATE 1:

I tried that:

  1. Rewrite class to Mage_Catalog_Block_Navigation

    class Company_Catalog_Block_Navigation extends Mage_Catalog_Block_Navigation
    {
        //...
    }
    
  2. Add function renderOtherCategoriesMenuHtml to Company_Catalog_Block_Navigation

    public function renderOtherCategoriesMenuHtml($otherRootID, $level = 0, $outermostItemClass = '', $childrenWrapClass = '')
    {
        $activeCategories = array();
    
        $categories = Mage::helper('catalog/category')->getOtherStoreCategories(otherRootID);
    
        foreach ($categories as $child) {
            if ($child->getIsActive()) {
                $activeCategories[] = $child;
            }
        }
    
        $activeCategoriesCount = count($activeCategories);
        $hasActiveCategoriesCount = ($activeCategoriesCount > 0);
    
        if (!$hasActiveCategoriesCount) {
            return '';
        }
    
        $html = '';
        $j = 0;
        foreach ($activeCategories as $category) {
            $html .= $this->_renderCategoryMenuItemHtml(
                $category,
                $level,
                ($j == $activeCategoriesCount - 1),
                ($j == 0),
                true,
                $outermostItemClass,
                $childrenWrapClass,
                true
            );
            $j++;
        }
    
        return $html;
    }
    
  3. Rewrite class Mage_Catalog_Helper_Category and add custom function:

    class Company_Catalog_Helper_Category extends Mage_Catalog_Helper_Category{
    
    public function getOtherStoreCategories($idParent, $sorted=false, $asCollection=false, $toLoad=true)
    {
    
        $cacheKey   = sprintf('%d-%d-%d-%d', $idParent, $sorted, $asCollection, $toLoad);
    
        if (isset($this->_storeCategories[$cacheKey])) {
            return $this->_storeCategories[$cacheKey];
        }
    
        /**
         * Check if parent node of the store still exists
         */
        $category = Mage::getModel('catalog/category');
        /* @var $category Mage_Catalog_Model_Category */
        if (!$category->checkId($idParent)) {
            if ($asCollection) {
                return new Varien_Data_Collection();
            }
            return array();
        }
    
        $recursionLevel  = max(0, (int) Mage::app()->getStore()->getConfig('catalog/navigation/max_depth'));
        $storeCategories = $category->getCategories($idParent, $recursionLevel, $sorted, $asCollection, $toLoad);
    
        $this->_storeCategories[$cacheKey] = $storeCategories;
        return $storeCategories;
    }
    }
    

4.Call renderOtherCategoriesMenuHtml in the view with navigation.

5.Incorrect rewrite urls:

After that you'll get navigation menu but it has incorrect rewrite rules. I debugged it. If we take a look at getCategories function in Mage_Catalog_Model_Resource_Category you will see this one:

$tree->addCollectionData(null, $sorted, $parent, $toLoad, true);

This method has some functionality which is set rewrite rules:

class Mage_Catalog_Model_Resource_Category_Tree extends Varien_Data_Tree_Dbp
{
      public function addCollectionData($collection = null, $sorted = false, $exclude = array(), $toLoad = true, $onlyActive = false)
      {
            //...
            if ($this->_joinUrlRewriteIntoCollection) {
                $collection->joinUrlRewrite();
                $this->_joinUrlRewriteIntoCollection = false;
            }
            //...
      }

This function get rules from core_url_rewrite where each request path attitudes to certain webstore. It means that we should create webstore and new store view to get its root category children with correct URL.

Resume: @RickKuipers is partly right but we shouldn't change webstore while view is being generated.

5
  • 2
    Why do you want to render two root categories? just create two subcategories and put them into your root category. This way you don't have this problem Jan 23, 2013 at 19:57
  • @FabianBlechschmidt, I like this suggestion, why not post it as an answer?
    – Luke Mills
    Jan 23, 2013 at 23:45
  • @LukeMills It had been an answer before) For some reason my comment disappeared. I would like to use one root category for different webstores. In this case I shouldn't create clone of this category in every webstore. That is why it is not suitable for me.
    – Anthony
    Jan 24, 2013 at 6:53
  • sorry anthony, I posted it as an answer, but as @jeremy1026 said, it is not an answer to the question :-) so better as comment. Jan 24, 2013 at 8:07
  • @Anthony To be honest there is nothing wrong with switching the current store for that 1 line, nothing happens when using setCurrentStore apart from a variable being set differently. As long as you set it back there's nothing that could raise a flag. Check the function yourself. Jan 24, 2013 at 12:13

2 Answers 2

3

My question would be why are you trying to use two root categories in the same store? A root category is intended to be just that, the parent of all categories which are available for use on a given store. It's a means of access control, URL construction and the list goes on. There are a vast number of places you would need to (literally) hack the core to make this work all around. Taking this route you will run into nuances which will most likely come back to bite you.

What I would suggest is to simple use one root category as intended by Magento and move all sub-categories you wish to show up to be children of it. Break down the hierarchy beneath the root. If you need to use this same structure for multiple stores which have the same product set, you can set the same root as the root of multiple stores when creating them in the admin.

Sometimes the best way to solve problems like this is not jumping into the code and changing stuff up, but rather looking at the approach being taken and finding another way to accomplish your goals without needing to make such awkward changes to the core. You will benefit now and in the long run by using this methodology. In the short-term you will benefit from less modifications and get up and running more quickly, and in the long-run you will also benefit from less modifications because when it comes time to upgrade you won't have to port intrusive changes to the way the core functions to the newer versions of Magento.

2
  • 1
    Thx for detailed answer! I need show one "subroot" category for each store and the other one just for current webstore. In another words each webstore should has access to general root category and shouldn't has access to others except current webstore category root.
    – Anthony
    Jan 24, 2013 at 15:05
  • 1
    That being the case, you should be able to have one hierarchy of categories with one root just fine. Simply set the Is Active attribute on store specific categories to No at the global level, then set it to Yes on the Store Views which it should display on, or vice-versa where you disable it on the store views it should not display on.
    – davidalger
    Jan 26, 2013 at 17:40
1

You can temporarily change the current store to the other store and execute that same function:

$oldStore = Mage::app()->getStore();
$_menu1 = $this->renderCategoriesMenuHtml(0, 'level-top');
Mage::app()->setCurrentStore('store2');
$_menu2 = $this->renderCategoriesMenuHtml(0, 'level-top');
Mage::app()->setCurrentStore($oldStore);

setCurrentStore() takes a store code. I haven't tested this but I think it will work just fine, perhaps with a little tweaking.

EDIT

Just put this to test and works perfectly fine.

5
  • Thanks for your answer. Unfortunatly it doesn't get work. It looks like temporary. We have one store abstraction. And it's better to avoid store switching.
    – Anthony
    Jan 23, 2013 at 19:08
  • @Anthony Unfortunately renderCategoriesMenuHtml() doesn't accept anything else but the current store's root category. Another way would be to read out the categories and the html itself. Jan 23, 2013 at 19:10
  • @Anthony I have just tested the code and it works fine, are you sure you put it in the right place and that you specified the right store code? Jan 23, 2013 at 19:32
  • Have you set view name for second store?
    – Anthony
    Jan 24, 2013 at 11:19
  • @Anthony I created a second Store with a view, gave the view a code (in this case I called it store2) and added the other root category to the store. Jan 24, 2013 at 11:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.