[Mini Tutorial] Adding Custom Links with local.xml

As with many other aspects of both software development and life, when working with Magento, the shortest path is not always the correct one to take for long term sustainability and growth. As I am sure that most of you know by now that very few items in Magento are simple, and everything in Magento has a right way to be done and a wrong way. Doing things the easy and quick way very often means doing it the wrong way. If you can find the patience within you to take the time and do things the correct way, you will be greatly rewarded in the future!

Homer Hiding

If you’re feeling like this right now, don’t worry. It’s not as hard as it seems after you know what you’re doing.

Related: [Mini-Tutorial] Magento and WordPress Multisite Integration

BEST PRACTICES

You’re probably here because you want to learn how to add links through xml in Magento – which is great! Adding links through xml is considered best practice. Why is it though? Well, one reason is the fact that they get cached, so keep in mind you should only create links this way if they’re meant to be static and not dynamic links.

Another reason xml links are best practice is because they are flexible. It allows you to easily add them per page, or on logged in and logged out, they have translations and you can use helpers to generate the labels and urls.

If these custom links should need to be easily editable though, maybe by you or by your client, and you have no need to worry about cache. It is also best practice to place them in a static block.

When not to add links through xml:

Let’s say you want your site to say hello to a customer with their name once they’re logged in. If you created those links in the layout (the way it’s shown in this tutorial) when a customer logs in their name will get cached. So when the next customer tries to log in they will see the old cached customer’s name instead of their own if that cache has not expired yet. So, just remember that when you don’t want your links to be cached, you should write that code in the template files instead of layout.

Related:Mini Tutorial: Removing Customer Account Navigation Links via Layout XML

TUTORIAL

Alright, enough talk about best practices, let’s get to the good part already! I will now show you the proper way to use xml to create custom static links.

Let’s say you want to add an ‘About Us’ link in the header. You’ll need to reference the header block and inside of it create a child block that will contain your custom link.

Go to your theme’s local.xml file. If you don’t have one yet you need to create it inside of your theme’s layout folder.

If this is the first time you are creating your local.xml remember you will need to have these tags inside of it

<?xml version="1.0"?>
<layout version="0.1.0">
    <!-- All xml code goes in here -->
</layout>

First thing you need to do is reference the header block inside of the default handles (since we want it to be on every page).

<default>
    <reference name="header">
        <block type="core/template" 
               name="header_nav" 
               as="headerNav"
               template="page/html/headernav.phtml">
        </block>
    </reference>
</default>

Inside of the reference we created the parent block that will hold our child links block. The core/template class makes it a more versatile block since it contains the most functions in it. We also gave it a name and as attributes and we gave it a template. That is a custom template we will need to create, and where we will call the child links block to render on the page.

<block type="core/template" name="header_nav" as="headerNav" template="page/html/headernav.phtml">
    <block type="page/template_links" 
                name="header.nav.custom.links" 
                as="customLinks">      
    </block>
</block>

In the code above we have created the child links block in our header_nav block. This time the type is page/template_links which is the class Magento uses to render xml links (You can find more info about this class’ functions in app/code/core/Mage/Page/Block/Template/Links.php). We also gave it name and as attributes which will come in handy when we need to reference it.

<block type="page/template_links" 
       name="header.nav.custom.links" 
       as="customLinks">
    <action method="addLink" translate="label title">
        <!-- Link parameters go in here -->
    </action>      
</block>

The final step in the xml is to just add the links with the method “addLink” as shown above. This is where it can get a bit complicated because links in xml need quite a bit of parameters to work properly. Here we’re adding the ‘About Us’ link.

<action method="addLink" translate="label title">
    <label>About Us</label>
    <url>about-us</url>
    <title>About Us</title>
    <prepare>true</prepare>
    <urlParams helper="core/url/getHomeUrl"/>
    <position>1</position>
    <liParams>id="about-us-li"</liParams>
    <aParams>class="top-link" id="about-us-top-link"</aParams>
    <beforeText/>
    <afterText>|</afterText>
</action>

line 2: This is the label. The text that the user will see as the link.
line 3: Here we have the URL to the about us page, we can also type out the full URL here if we decide to not use the base URL parameter on line 5.
line 4: This is the title attribute given to the <a> tag.
line 5: This parameter should be set to true when you want to use the base URL.
line 6: As you read above, this is the base URL and we get it with the helper.
line 7: This number is the position of the link in a list of links. I’d recommend using numbers like 10,20,50 etc. If one doesn’t work just try another.
line 8: liParams is used to add IDs to the ‘li’ you can’t add classes here because it conflicts with the classes Magento has already added.
line 9: Here you can add a class and/or an ID to the <a> tag.
line 10 – 11: These work just like the :before and :after pseudo classes in CSS, you can add any extra text or characters with these.

The HTML that this code renders looks like this.

<ul class="links">
    <li class="first" id="about-us-li">
        <a href="http://yoursite.com/about-us/" title="About Us" class="top-link" id="about-us-top-link">About Us</a>
        "|"
    </li>
</ul>

Go to your theme’s template folder and create a new template wherever you find it appropriate. Since they’re header links we place this template under ‘page/html‘ and name it ‘headernav.phtml‘ since that’s what we declared in the ‘headerNav‘ block.

<div class="links">
    <?php echo $this->getChildHtml('customLinks') ?>
</div>

A call to get the child links block with the as="customLinks" attribute we gave it is all the code you’ll need inside of it.

If you ever needed to edit the HTML that is rendered, i.e. place a wrapping <div> in-between the <li> and the <a> you could do this by copying and pasting the Magento links template code into a new template and customizing it the way you need. Then telling your custom links block to use that custom template. You can find the original links.phtml that Magento uses in page/template/. And here is how you tell the block to use it.

<block type="page/template_links" 
       name="header.nav.custom.links" 
       as="customLinks"
       template="path/to/custom-links.phtml">    
</block>

Or if you ever need to add some extra HTML markup in the actual link label, i.e. if you need one word to be a different colour from the rest of the link. You can add it like this:

<action method="addLink" translate="label title">
    <label>Explore a <![CDATA[<span>]]>better<![CDATA[</span>]]> way</label>
</action>

This XML will render this HTML

<ul class="links">
    <li class="first">
        <a href="">Explore a <span>better</span> way</a>
    </li>
</ul>

And that’s it! Hopefully you will continue to create links this way more often and eventually become a master of Magento’s best practices so you never write code that make other developers cringe and picture you at your computer like this…

I have no idea what I'm doing

Related: Magento Certified Solution Specialist (MCSS) Study Guide