in Magento, Tutorials

Theming for Magento — Part 04 – How it all works

Wow, part 4 already? This is where the real fun comes in, folks. Today we’ll be opening up some *.phtml and *.xml files, looking at what’s going on under the hood and finding out how the theme files all tie together. Lets get started, shall we?

Before we get to those files…

Folks, before we dive into the files, lets get some concepts down that are crucial to understanding how the Magento theme files play together.

Magento themes consist of, aside from styling assets (CSS, images, Javascript, etc) a collection of *.phtml (essentially, XHTML files that can execute PHP) and *.xml (Extensible Markup Language) files that make the theme work.

The *.xml files define blocks and regions, which template files get used for which blocks & regions as well as various attributes and parameters for each if these definitions, where applicable.

While the *.xml files tell everything where to be and what to look like, the *.phtml files contain the actual XHTML code required for each block and region.

  • At the time of writing this tutorial, I have upgraded my Magento installation to Community Edition 1.4. All further tutorials, as well as this one, will be  referencing Magento Community Edition 1.4 unless otherwise stated. Please be sure you have the latest version.

Blocks and regions? Huh?

Yes, blocks and regions.

Magento has a system called “Static Blocks”, which allows theme authors to define areas which are updatable via the administration console using a simple textarea. This is used, by default, in the footer as well as for one or two other areas, and can be very  useful for allowing the theme users to update small chunks of content on their store. These are referred to in this tutorial as “blocks”.

Regions. This is where we need to get conceptual.

The easiest way I’ve found to explain this concept is by comparing regions to widgetised areas in WordPress. When users create widgetised areas in WordPress, they are creating areas that are open for the user to insert blocks of content (widgets) that will take on appropriate styling. The region concept is similar.

In Magento, by default, certain blocks are placed in certain regions (for example, Layered Navigation in the left column). This is the reason why it is so important to make use of all possible template types when theming for Magento (3 columns, 2 columns, 1 column, etc), as there is a tried and tested reason why each block is placed in a particular region. This can, however, be modified via the *.xml file (which does all the “do this, do that”, remember?), so its not a major worry if you need to move a block.

So, what’s a *.phtml file anyway?

A *.phtml file is a template file. It can either define a page template to be used when displaying a particular type of page (product page, category page, CMS page, etc) or a template to be used in a particular area, for example, the way each single product is displayed when a category is in list mode or grid mode, or the way your footer links static block (activated by default when Magento is installed) is displayed within your theme.

Lets take a look at a fairly standard *.phtml file, 2columns-right.phtml, found in your theme’s directory within the “app > design” folder.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<html xmlns="" xml:lang="<?php echo $this->getLang() ?>" lang="<?php echo $this->getLang() ?>">
<?php echo $this->getChildHtml('head') ?>
<body<?php echo $this->getBodyClass()?' class="'.$this->getBodyClass().'"':'' ?>>
<?php echo $this->getChildHtml('after_body_start') ?>
<div class="wrapper">
    <?php echo $this->getChildHtml('global_notices') ?>
    <div class="page">
        <?php echo $this->getChildHtml('header') ?>
        <div class="main-container col2-right-layout">
            <div class="main">
                <?php echo $this->getChildHtml('breadcrumbs') ?>
                <div class="col-main">
                    <?php echo $this->getChildHtml('global_messages') ?>
                    <?php echo $this->getChildHtml('content') ?>
                <div class="col-right sidebar"><?php echo $this->getChildHtml('right') ?></div>
        <?php echo $this->getChildHtml('footer') ?>
        <?php echo $this->getChildHtml('before_body_end') ?>
<?php echo $this->getAbsoluteFooter() ?>

The above code is a direct copy/paste of the 2columns-right.phtml file, packaged with the base > default theme in Magento 1.4. The use of $this->getChildHtml() is directed at retrieving specific template files, declared within the page.xml file. The other functions, getAbsoluteFooter() and getBodyClass() are, for the scope of this tutorial, not relevant.

… and the XML?

This file defines our regions, sets up blocks within those regions and tells each region which template to use. It is also used for loading theme-specific CSS and JavaScript, as well as activating and deactivating blocks within specific regions in particular sections of your Magento theme. Essentially, the XML file controls everything related to the module in question.

In most cases, the majority of your time when theming will be spent within page.xml. As this file is well and truly gigantic for pasting into a blog post (approximately 182 lines), I’ll paste just the relevant snippets for getting the aim of this tutorial across.

<block type="core/text_list" name="left" as="left" translate="label">
<label>Left Column</label>
What you see above is the creation of the region called “left”. This is telling Magento that we have a region called “left”, to which blocks in a multitude of modules can be assigned. This is a blank area of the theme, to which content, in the form of blocks, is pointed (emphasising the point, there).
<reference name="left">
<block type="core/template" name="left.permanent.callout" template="callouts/left_col.phtml">
<action method="setImgSrc"><src>images/media/col_left_callout.jpg</src></action>
<action method="setImgAlt" translate="alt" module="catalog"><alt>Our customer service is available 24/7. Call us at (555) 555-0123.</alt></action>
<action method="setLinkUrl"><url>checkout/cart</url></action>

The block of code above is from catalog.xml, the controller XML file for all things related to the Magento catalog. The above block of code creates one of the default callout blocks (a block with an image and a URL) that is bundled with the default Magento theme. Lets spend some time on this block of code.

So… how do I use these files?

The first and last lines, in this case, are the most important. They tell Magento that anything within them (ie: the block inside the <reference> tags) will be assigned to the “left” region. Inside that, the <block> tags setup the callout block with it’s various attributes. As the <action> tags are rather specific to this callout (they use specific image-related methods to setup the source of the image, it’s alternate text and the URL to which it points), lets focus on the opening <block> tag.

The opening <block> tag has the following attributes: type, name and template. These do exactly what they say on the tin.

type- Tells Magento what type of block this is (it could be a product list, catalog, a display of only new products, etc). This is dependent on the type of content within the block. In this case, it’s a raw image using a specific template, so it’s a core/template.

name- What this block is referred to as within the XML files.

template- What template file is used to render this block within the theme. In this case, it’s a template called left_col.phtml within the “callouts” folder. This file looks like this:

<div class="block block-banner">
<div class="block-content"> <?php if(strtolower(substr($this->getLinkUrl(),0,4))==='http'): ?> <a href="<?php echo $this->getLinkUrl() ?>" title="<?php echo $this->__($this->getImgAlt()) ?>"> <?php elseif($this->getLinkUrl()): ?> <a href="<?php echo $this->getUrl($this->getLinkUrl()) ?>" title="<?php echo $this->__($this->getImgAlt()) ?>"> <?php endif; ?> <img src="<?php echo $this->getSkinUrl($this->getImgSrc()) ?>"<?php if(!$this->getLinkUrl()): ?> title="<?php echo $this->__($this->getImgAlt()) ?>"<?php endif; ?> alt="<?php echo $this->__($this->getImgAlt()) ?>" /> <?php if($this->getLinkUrl()): ?> </a> <?php endif ?> </div> </div>

Above you can see some familiar functions such as getImgSrc() (related to setImgSrc() within the XML file). These functions retrieve the data that is set within the <reference> tags in the XML file.

… and to sum it all up …

Okay. Lets sum this up in a single paragraph.

Wherever dynamic content is set within your theme, it is more often than not done using a region. These regions are usually set within the page.xml file, as the “page” module defines the main skeleton of the Magento theme. Blocks specific to the module they work with are set in that modules XML file, with a <reference> to the region in which they are displayed. A template file, usually stored within the module in question, is used to render the content that is retrieved by the block it is used on.

Wow, this was a busy tutorial. There’s a lot to take in above, folks. If any of it seems unclear, please leave a comment and I’ll do my best to help clarify things.

Write a Comment


  1. I need to set up an online e commerce site for my business.

    Magento seems like such an amazing application to get into, I downloaded and installed it successfully and started working through some tutorials. I don’t have a lot of coding background and I am finding the whole learning curve very daunting. Am I wasting my time as a novice? Where is the right place to start and what should my road map be? I will appreciate any guidance/advice

    • Hi Pieter,
      Thanks for your comment.

      I don’t think it’s a waste of time at all. I’d say, take it slowly and learn as much as you can.

      In terms of getting your store online, I’d recommend reading through the earlier tutorials in this collection and get your own theme set up (basicly, make a copy of the default theme, as explained in the tutorials). From there, I’d recommend working with the CSS and images without working with the PHTML and XML files. A lot can be accomplished through modifying only the styling of the store, and this should also help to give a better idea of how things are structured within Magento themes.

      In addition to the above, I’d recommend keeping the use of Magento Extensions to a minimum. No need to go down that road yet when just starting out. 🙂

      I hope this helps, Pieter. If there’s anything I can clarify, please let me know.


  2. Hi Matty!
    Thanks a lot for your tutorial. I’ve been searching on the internet for 1.4 Themes tutorial but couldn’t find really good once.
    I still don’t get the logic behind all this XML files. For example, I wanted to integrate Magento with Joomla but the only good bridge is not for free, so I decided to install Magento in a sub-folder an try to mimic in Magento the Joomla website template.

    The point where I go stuck is this:
    -I want to create a custom-top-navigation block in Magento’s header and hand-code all the links from Joomla site and I’ll visually have two identical websites with different content.

    How can I create such a block with all this XML and phtml file.

    I’d really appreciate your help!

    • Hi Paul,
      Thanks for your comment.

      For your custom menu, you could code the menu in header.phtml, using the following structure:

      	<li><a href="<?php echo $this- rel="nofollow">getUrl('/example'); ?>"><span><?php echo $this->__('Link Text'); ?></span></a></li>

      Essentially, the getUrl() method generates a URL with your Magento URL as the base. You could also hard-code the URLs, although this wouldn’t be ideal. Using $this->__() enables localisation of your text, for translators to create files that allow your code to be translated into other languages. Even if it’s not necessary in the context of your project, it’s a good practice that’s worth getting into. 🙂

      The only time the XML files would come into play is if you want to move your new navigation into a separate file. This, however, isn’t essential to make the navigation work.

      I hope this answers your question, Paul. 🙂

      All the best,