Links in the Magento header (topLinks) are often little used or used the wrong way and numerous developers prefer creating a template file. While this causes more blocks to generate for Magento, it may lower code readibility and ease of maintenance. Whereas topLinks have some wonderful hidden features.


What's happening

First of all, topLinks are added to the layout in the page.xml file, around line 80 :

// app/design/frontend/base/default/layout/page.xml

<block type="page/template_links" name="top.links" as="topLinks"/>  

We can then tell that the class in charge of generating topLinks is Mage_Page_Block_Template_Links. And that is where all the magic happens, with the method addLink() that can get several arguments allowing us to specify the look and behavior of links displayed in the header.

Another interesting method is addLinkBlock() that allows us to directly add any block. In other words, this method gives us the ability to add any content to the topLinks.

In order to use these methods, we just have to call them in the XML layout files. So easy. There is an example in the customer.xml layout file, around line 51 :

<reference name="top.links">  
    <action method="addLink" translate="label title" module="customer"><label>My Account</label><url helper="customer/getAccountUrl"/><title>My Account</title><prepare/><urlParams/><position>10</position></action>
</reference>  

You can now have fun by digging into this Mage_Page_Block_Template_Links class but here are a few examples making an interesting use of topLinks.

<reference name="top.links">  
    <action method="addLink" translate="label title">
        <label>Go to google.com</label>
        <url>http://www.google.com</url>
        <title>Visit google.com</title>
        <prepare/>
        <urlParams/>
        <position>200</position>
        <liParams/>
        <aParams/>
        <beforeText/>
        <afterText/>
    </action>
</reference>  
<reference name="top.links">  
    <action method="addLink" translate="label title">
        <label>Who we are</label>

        <!-- URL identifier of a CMS page -->
        <url>about-magento-demo-store</url>

        <title>About our Store</title>

        <!-- Ask Magento to convert <url> identifier of the CMS page to a link relative to our domain -->
        <prepare>1</prepare>

        <urlParams/>
        <position>200</position>

        <!-- Adding a class param to the <li> of the link. Any param passed in liParams node will be added to the rendered <li> -->
        <liParams>
            <class>top-links-about-us</class>
        </liParams>

        <!-- Adding inline style to the <a> tag of the link. Any param passed in aParams node will be added to the rendered <a> -->
        <aParams>
            <style>font-weight: bold; color: red;</style>
            <target>blank</target><!-- Though this is not recommended, this is for the sake of the example -->
        </aParams>

        <!-- Some text added before the <a> -->
        <beforeText>
            <![CDATA[<span style="color: red">&gt;</span>]]>
        </beforeText>

        <!-- Some text after before the <a> -->
        <afterText>
            <![CDATA[<span style="color: red">&lt;</span>]]>
        </afterText>
    </action>
</reference>  

Add twice the product with ID 1 to the cart

<reference name="top.links">  
    <action method="addLink" translate="label title">
        <label>Buy our best selling product now!</label>
        <url>checkout/cart/add</url>
        <title>Buy our best selling product now!</title>
        <prepare>1</prepare>

        <!-- Add params to the URL like <param>value</param> -->
        <urlParams>
            <product>1</product>
            <qty>2</qty>
        </urlParams>

        <position>200</position>
        <liParams/>
        <aParams/>
        <beforeText/>
        <afterText/>
    </action>
</reference>  

Add newest product to the cart

<reference name="top.links">  
    <block type="toplinks/newest" name="toplinks_buy_newest_link">
        <action method="addBuyNewestLink"></action>
    </block>
</reference>  

Please note that instead of calling addLink(), we inject a block with a type coming from some module (toplinks/newest in this example). We then call any method from this custom block (addBuyNewestLink() in this example). This method will then be in charge of adding a link by calling Mage_Page_Block_Template_Links::addLink().

Here is the addBuyNewestLink() method of our example

public function addBuyNewestLink()  
{
    $parentBlock = $this->getParentBlock();

    $collection = Mage::getResourceModel('catalog/product_collection');
    Mage::getModel('catalog/layer')->prepareProductCollection($collection);
    $collection->setOrder('created_at')
        ->addStoreFilter()
        ->setPageSize(1);

    $newestProduct = $collection->getFirstItem();
    $label = $this->__("Add '%s' to cart now!", $newestProduct->getName());

    $parentBlock->addLink($label, 'checkout/cart/add', $label, true, array('product' => $newestProduct->getId()), 1000);
    return $this;
}

Add the content of a template file

<reference name="top.links">

    <!-- Add a template which name is "toplinks_notice" -->
    <block type="core/template" name="toplinks_notice" template="toplinks/notice.phtml">
        <action method="setPosition"><position>1</position></action>
    </block>

    <action method="addLinkBlock">
        <!-- Note that the <blockName> is the name of the template added just above -->
        <blockName>toplinks_notice</blockName>
    </action>
</reference>  

And the template file...
Of course, we need to code the template file (toplinks/notice.phtml in our example).

<li>  
    <div class="block">
        <div class="block-content">
            <p class="block-subtitle"><?php echo $this->__('Our products are the best ever!')?>
        </div>
    </div>
</li>  

It's all the same!

Example module

An example module is available here: https://github.com/herveguetin/Herve_TopLinks.