2

I would like to offer my product catalog only to customers that are logged in.

Is there a way I can hide my category navigation from visitors that aren't logged in to their account?

3

Add the following node to your layout.xml (of course put there appropriate parameters for your navigation placement block type and template):

<customer_logged_in>
    <reference name="your-navigation-area">
        <block type="your/nav" name="your_nav" template="your/nav-template.phtml" />
    </reference>
</customer_logged_in>

Edit: On the other hand, the better way would be maybe to remove the nav for logged out (still in your layout.xml):

<customer_logged_out>
    <remove name="your_nav"/>
</customer_logged_out>
| improve this answer | |
  • I'd like to try your method dmakabr but I don't have a layout.xml file. Is there a different file I would add this in? – Melissa Byram Dec 18 '14 at 17:05
  • OK I found the file you're talking about. In this situation, I have an extension that is controlling my navigation menu so I found the file in /app/design/frontend/base/default/layout/catsidebarnav.xml I added your second suggestion to the file towards the bottom right before </layout> and it works perfectly! Thank you soooo much! – Melissa Byram Dec 18 '14 at 20:36
4

Theory

The topmenu part of magento is actually including via page.xml layout update file. This specific layout XML file is actually used to define magento's layout structure. This is how it is defined in there

<block type="core/text_list" name="top.menu" as="topMenu" translate="label">
     <label>Navigation Bar</label>
     <block type="page/html_topmenu" name="catalog.topnav" template="page/html/topmenu.phtml"/>
</block>

The block definition gives us two hints.

1) topmenu block is of type Mage_Page_Block_Html_Topmenu.

2) Template that is associated with the topmenu block is app/design/frontend/<package>/<theme>/template/page/html/topmenu.phtml

Now have a look on topmenu.phtml. This is what you can see there

File : app/design/frontend/base/default/template/page/html/topmenu.phtml

<?php $_menu = $this->getHtml('level-top') ?>
<?php if($_menu): ?>
<div class="nav-container">
    <ul id="nav">
        <?php echo $_menu ?>
    </ul>
</div>
<?php endif ?>

So the single line $this->getHtml('level-top') is what makes the entire topmenu.

How category links are included in topmenu section then ? The best and simple answer for this question is, it is hard-coded in magento. But if you are more interested, you should study Mage_Catalog module.

Cheapest and the fast method

So if you want to hide topmenu from not-logged in users, then the fastest solution would be enclose the content of topmenu.phtml inside this condition.

 <?php if (Mage::getSingleton('customer/session')->isLoggedIn()) : ?>

      <!-- topmenu.phtml contents comes here -->
 <?php endif; ?>

So the condition check whether a valid customer exist in customer session. If yes it will show topmenu. Otherwise it is not.

The Best Way is Module Way

The above method is a core hack. So it should be avoided in any case. My recommendation is use a module way. This is the right thing. I am gonna call this module as Rkt_Tmli.

First let us inform magento about our module

File : app/etc/modules/Rkt_Tmli.xml

<config>
    <modules>
        <Rkt_Tmli>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Catalog />
                <Mage_Customer />
            </depends>
        </Rkt_Tmli>
    </modules>
</config>

By this definition, we are saying to magento that our module is depending upon Mage_Catalog and Mage_Customer, so that magento will load this two core modules before our module.

Let us define configurations of our module

File : app/code/local/Rkt/Tmli/etc/config.xml

<config>
    <modules>
        <Rkt_Tmli>
            <version>1.0.0</version>
        </Rkt_Tmli>
    </modules>
    <global>
    <models>
        <rkt_tmli>
            <class>Rkt_Tmli_Model</class>
        </rkt_tmli>
        </models>
    </global>
    <frontend>
        <events>
            <page_block_html_topmenu_gethtml_after>
                <observers>
                    <remove_topmenu_for_not_loggedin_customers>
                        <class>rkt_tmli/observer</class>
                        <method>checkTopmenu</method>
                        <type>singleton</type>
                    </remove_topmenu_for_not_loggedin_customers>
                </observers>
            </page_block_html_topmenu_gethtml_after>
        </events>
    </frontend>
</config>

If you look here, we are actually observing to an event page_block_html_topmenu_gethtml_after. This particular event will be processed before topmenu section is constructing in layout. So this is the best place to check our condition. So let us do that in an observer.

File : app/code/local/Rkt/Tmli/Model/Observer.php

<?php
class Rkt_Tmli_Model_Observer
{
    public function checkTopmenu(Varien_Event_Observer $observer)
    {
        $categoryNode = array();

        //customer is not logged in, then proceed
        if(!Mage::getSingleton('customer/session')->isLoggedIn()){

            //topmenu tree node;
            $menu = $observer->getEvent()->getMenu();

            //check topmenu tree has any children
            if ($menu->hasChildren()) {

                //get all children nodes of topmenu tree node
                $topmenuChildrenNodes = $menu->getChildren()->getNodes();

                //iterate through them and finds all category nodes
                //for category node `id` field is set to `id`.
                //for more details, check class Mage_Catalog_Model_Observer::_addCategoriesToMenu
                foreach ($topmenuChildrenNodes as $node) {

                    if ($node->getIdField() == 'id') {
                        $categoryNode[] = $node;
                    }
                }

                //removing all category nodes from topmenu tree
                foreach ($categoryNode as $node) {
                    $menu->removeChild($node);
                }

            }

        }

        return true;
    }
}

Our observer seems big. What we do here is, we are removing all category nodes from topmenu so that all other nodes except the category nodes still visible for not-logged in customer. If you dont want this and want to remove all topmenu links, you can use this code

<?php
class Rkt_Tmli_Model_Observer
{
    public function checkTopmenu(Varien_Event_Observer $observer)
    {
        $categoryNode = array();

        //customer is not logged in, then proceed
        if(!Mage::getSingleton('customer/session')->isLoggedIn()){

            //topmenu tree node;
            $menu = $observer->getEvent()->getMenu();

            //check topmenu tree has any children
            if ($menu->hasChildren()) {

                //get all children nodes of topmenu tree node
                $topmenuChildrenNodes = $menu->getChildren()->getNodes();

                //iterate through them and finds all category nodes
                foreach ($topmenuChildrenNodes as $node) {

                    $menu->removeChild($node);
                }

            }

        }

        return true;
    }
}

Hope that will help you.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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