So you want to make a theme for Magento?

You picked a tough gig, Chap.

When I first began learning Magento 1.6, I found a lot of outdated or downright wrong information on the right way to create a theme. So I made mistakes. A lot of them. And then I promised myself I would create a (3,000 word) tutorial to help others and spare them the headache.

So consider this your all-inclusive guide to Magento 1.6 theming: from the installation to a finished product.

Installing Magento 1.6.1

This guide will use Ubuntu as the operating system of choice. If you aren’t running a Linux distribution, you may run into some problems that won’t be covered in this guide. Did you know Ubuntu was free? Get it here and run a dual boot, or even run it as a virtual machine.

Using Subversion to Grab The Project

Let’s create the Magento directory we will be working in and then download the project via Subversion.

1 2 3 $ mkdir / var / www / Magento $ cd / var / www / Magento $ svn checkout http : //svn.magentocommerce.com/source/branches/1.6/ $ mkdir /var/www/Magento $ cd /var/www/Magento $ svn checkout http://svn.magentocommerce.com/source/branches/1.6/

It’s possible the above URL will change. A minor release may come about or the branch will be moved. In that case, you may find details you need on the Magento SVN page.

Creating The Database

Magento uses MySQL for its database. You will need MySQL installed and change out the username to fit your own. I’m using a super user, so in your case you might have to create your own Magento user and assign privileges accordingly.

1 2 $ mysql - u root - p mysql > CREATE DATABASE magento ; $ mysql -u root -p mysql> CREATE DATABASE magento;

Setting Up The Virtual Host

We will be accessing the project through the http://magento.local/ path. First we tell Ubuntu to redirect any traffic to that domain to our localhost, then setup Apache to handle the request.

1 sudo gedit / etc / hosts sudo gedit /etc/hosts

Add this line:

1 127 . 0 . 0 . 1 magento . local 127.0.0.1 magento.local

Now create a virtual hosts file that tells Apache how to handle our request. 000-default is probably already in your Apache2 folder. If you don’t have any other vhosts setup, you’ll want to create 001-magento.

1 2 cd / etc / apache2 / sites - enabled / sudo gedit 001 - magento cd /etc/apache2/sites-enabled/ sudo gedit 001-magento

Add this to the file:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 < VirtualHost *: 80 > ServerAdmin webmaster @ localhost ServerName magento . local DocumentRoot / var / www / Magento / 1.6 / < Directory /> Options FollowSymLinks AllowOverride All </ Directory > < Directory / var / www / Magento / 1.6 /> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow , deny allow from all </ Directory > ErrorLog $ { APACHE_LOG_DIR } / error . log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog $ { APACHE_LOG_DIR } / access . log combined </ VirtualHost > <VirtualHost *:80> ServerAdmin webmaster@localhost ServerName magento.local DocumentRoot /var/www/Magento/1.6/ <Directory /> Options FollowSymLinks AllowOverride All </Directory> <Directory /var/www/Magento/1.6/> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>

Restart Apache and check it out!

1 sudo service apache2 restart sudo service apache2 restart

If things went well you should see the install. The install process is simple, so let’s skip to setting Magento up for development.

Set Magento Up For Development

Developing on Magento is a pain if you are using the settings for the production environment. Let’s make development easy on ourselves!

File Ownership and Permissions

Since we are working on development, we can skip some headaches from permissions and ownership issues:

1 2 $ cd / var / www / $ sudo chmod - R 777 Magento $ cd /var/www/ $ sudo chmod -R 777 Magento

Check the owner of the files, and recursively use chown if necessary.

Disable The Cache

It’s fantastic that Magento comes with the ability to cache everything and anything, but this is poor for development. Save yourself from clearing the cache on each change by disabling it completely.

Go to System -> Cache Management Select all and disable Success!

Enabling Errors

When something goes wrong we want to know about it. In your index.php file simply uncomment line 70:

1 ini_set ( 'display_errors' , 1 ) ; ini_set('display_errors', 1);

Starting Our Theme Development

There are two main parent directories that will be used to run a theme.

/app/design/frontend/ – This contains all the logic and markup for your theme. /skin/frontend/ – This contains all the styles, javascript, and images for your theme.

Look around a bit. There are a lot of files! It may seem easier to copy an existing theme and hollow it out to make your own. This is a bad idea: there will be quite a bit of excess code, and you won’t learn the Magento theme structure as you should.

Create a New Package

Before we get started, a word of caution: never edit the base package. It contains all the fallback files that are used when Magento can’t find a certain file. In addition, a Magento update will overwrite changes to the base package.

A package may contain a number of themes. For instance, you will see the default package has a default and modern theme. If you wanted you could create a new theme inside the default package, but we are rolling our own named Vacancy:

Create the package templates folder: /app/design/frontend/vacancy-package/ Create the package styles folder: /skin/frontend/vacancy-package/

Alright chief, this is your directory structure so far:

Create A New Theme

You may have multiple themes for each package. Our package will actually have two themes: default and vacancy-theme. The base package works as a great fallback, but we will be copying the default theme to our own package. Then we won’t have to touch any files that aren’t pertinent to our project.

Copy from and to:

1 2 / app / design / fontend / base / default / / app / design / frontend / vacancy - package / default / /app/design/fontend/base/default/ /app/design/frontend/vacancy-package/default/

Excellent. Now if Magento can’t find a file, it will use our package’s default theme to find it. Just like the base package, you shouldn’t edit this theme.

No need to copy over your styles and images: we will be using our own basic design for this tutorial.

The game so far:

Enabling The New Package and Theme

Magento doesn’t yet know we want to use our own package and theme — let’s tell it!

Go to System -> Configuration Go to General -> Design Add in our package and theme like so:

Refresh the home page and you will see an un-styled beast of a theme. Let’s get Vacancy styled, shall we?

Creating The Homepage

The base theme we are working with is dubbed Vacancy. It’s a high-end design, as you can see:

Alright, maybe not high end, per se, but for our purposes it will explain the concept of themes famously.

Your skin directory should look like this once you plop in the CSS file:

You won’t directly use the index.php file, but you should still take a good look at it. It gets chopped up into sections, modules, and blocks before we are able to use it in our actual theme.

Working With Magento XML Layout Files

Magento uses XML files to pass important layout information to our view. This could include a module, template file locations, or adding Javascript files to our header.

In the default theme, you will see three major folders:

etc

layout

template

We are concerned with the layout and template folders. Layout contains the XML files, while the template folder contains PHTML files.

The XML files structure the content by blocks, while the PHTML files contain our actual markup. This should be more clear when we work with these files more.

To get an idea of this concept, open two files from the default theme:

/layout/page.xml – This contains the mentioned structural code. Our own page.xml will be drastically simplified. /template/page/2columns-left.phtml – This contains markup for one of the default layouts, which has two columns and a left sidebar. As you can see, Magento simplifies the layout to a great extent by allowing for blocks and sections to be included as needed.

Let’s create our own page.xml file — this will be the default fallback for all pages. Ours will be a hollowed-out version of the version you just saw:

/app/design/frontend/vacancy-package/vacancy-theme/layout/page.xml

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 < layout version = "0.1.0" > <!-- Default layout , loads most of the pages --> < default translate = "label" module = "page" > < label > All Pages </ label > < block type = "page/html" name = "root" output = "toHtml" template = "page/vacancy-2columns.phtml" > <!-- Add Styles to Head --> < block type = "page/html_head" name = "head" as = "head" > < action method = "addCss" >< stylesheet > css / style . css </ stylesheet ></ action > </ block > <!-- Our Header --> < block type = "page/html_header" name = "header" as = "header" translate = "label" > < label > Header </ label > </ block > <!-- Our Sidebar --> < block type = "catalog/navigation" name = "sidebar" as = "sidebar" translate = "label" template = "catalog/navigation/sidebar.phtml" > < label > Sidebar </ label > </ block > <!-- Main Content Area --> < block type = "core/text_list" name = "content" as = "content" translate = "label" > < label > Main Content Area </ label > </ block > <!-- The Footer --> < block type = "page/html_footer" name = "footer" as = "footer" template = "page/html/footer.phtml" > < label > Footer </ label > </ block > </ block > </ default > </ layout > <layout version="0.1.0"> <!-- Default layout, loads most of the pages --> <default translate="label" module="page"> <label>All Pages</label> <block type="page/html" name="root" output="toHtml" template="page/vacancy-2columns.phtml"> <!-- Add Styles to Head --> <block type="page/html_head" name="head" as="head"> <action method="addCss"><stylesheet>css/style.css</stylesheet></action> </block> <!-- Our Header --> <block type="page/html_header" name="header" as="header" translate="label"> <label>Header</label> </block> <!-- Our Sidebar --> <block type="catalog/navigation" name="sidebar" as="sidebar" translate="label" template="catalog/navigation/sidebar.phtml"> <label>Sidebar</label> </block> <!-- Main Content Area --> <block type="core/text_list" name="content" as="content" translate="label"> <label>Main Content Area</label> </block> <!-- The Footer --> <block type="page/html_footer" name="footer" as="footer" template="page/html/footer.phtml"> <label>Footer</label> </block> </block> </default> </layout>

It’s a good time to review blocks. In Magento, blocks serve the purpose of grouping together items in your template.

In our case, our blocks are the head, header, sidebar, content area, and the footer.

You will notice that the root block references a template file, vacancy-2columns.html. Let’s create that now.

/vacancy-theme/template/page/vacancy-2columns.phtml

For now just put the contents of our index.php file you downloaded earlier and save it.

Refresh the page.

Doesn’t work too well, does it? That’s because the homepage in Magento is currently a CMS page. In your admin panel:

Go to CMS -> Pages Go to Homepage -> Design

In the dropdown to select the design for the homepage you will note our theme and package is there, but our layout isn’t. The dropdown is being populated by an XML file so it isn’t dynamic.

And now more bad news: editing this dropdown isn’t as easy as you would think.

Setting Template Layouts for CMS Pages

There are two methods of altering your CMS page layouts.

Creating a module is the accepted way, but by simply making a module we won’t be able to remove the base layouts from the list. Not a big deal, but for the OCD impaired it’s sure painful.

Extending a core Magento file is the second way, and it has the benefit of giving you full control of what is in the list. The problem is that we are extending a configuration file — this is generally looked down upon because upgrades might significantly change the file. That means work will have to be done to update your installation before upgrading. This is somewhat a non-issue: if you have extended core files, you should already know that you’ll have to take a look at them before upgrading.

We’ll go through both methods since they both teach valuable lessons. Afterward you may decide which you want to side with.

Method One – Extending Magento Core Code

Magento keeps it’s base code in /code/core/Mage/. Do not ever modify these files directly. Your changes will be overwritten when you upgrade Magento. Instead, we have to extend the core files.

The files we want are located in:

/app/code/core/Mage/Page/etc/config.xml /app/code/core/Mage/Page/etc/system.xml

Copy both of these over to a new path:

/app/code/local/Mage/Page/etc/

Look at the config.xml file and you’ll see how templates are being built. Just remove the <layouts> code and put the following in:

/app/code/local/Mage/Page/etc/config.xml

1 2 3 4 5 6 7 8 9 < page > < layouts > < vacancy_two_columns module = "page" translate = "label" > < label > Vacancy 2 Columns </ label > < template > page / vacancy - 2columns . phtml </ template > < layout_handle > page_vacancy_two_columns </ layout_handle > </ vacancy_two_columns > </ layouts > </ page > <page> <layouts> <vacancy_two_columns module="page" translate="label"> <label>Vacancy 2 Columns</label> <template>page/vacancy-2columns.phtml</template> <layout_handle>page_vacancy_two_columns</layout_handle> </vacancy_two_columns> </layouts> </page>

We don’t actually modify system.xml. Since there will be no fallback, we have to include all original files whether we modify them or not.

Now let’s tell Magento to use our local code instead of the core code! Find Mage_All.xml here:

/app/etc/modules/

Find the Mage_Page block and tell it to use local code like so:

/app/etc/modules/Mage_All.xml

1 2 3 4 5 6 7 < Mage_Page > < active > true </ active > < codePool > local </ codePool > < depends > < Mage_Core /> </ depends > </ Mage_Page > <Mage_Page> <active>true</active> <codePool>local</codePool> <depends> <Mage_Core/> </depends> </Mage_Page>

If all went well you may now go to your CMS Homepage settings and use our theme:

Refreshing the homepage, you should see that we are now using the new layout. The CSS shouldn’t load correctly at this point. We’ll get to that after reviewing the second method of changing CMS layouts.

Method 2 – Creating A Magento Module

Creating a module is easy. We create a new XML file in /etc/modules/ named Vacancy_CMSTemplates.xml.

Fill your XML file with the following code:

/etc/modules/Vacancy_CMSTemplates.xml

1 2 3 4 5 6 7 8 9 10 11 12 <? xml version = "1.0" ?> < config > < modules > < Vacancy_CMSTemplates > < active > true </ active > < codePool > local </ codePool > < depends > < Mage_Page /> </ depends > </ Vacancy_CMSTemplates > </ modules > </ config > <?xml version="1.0"?> <config> <modules> <Vacancy_CMSTemplates> <active>true</active> <codePool>local</codePool> <depends> <Mage_Page /> </depends> </Vacancy_CMSTemplates> </modules> </config>

Note that we named the module “Vacancy_CMSTemplates” – this is important to remember as it also tells Magento where our module code will reside. In this case we create our config.xml file at the following:

/app/code/local/Vacancy/CMSTemplates/etc/config.xml

The XML file will have to tell Magento to add our own layouts to the global scope. All we do is add our same XML layout code like so:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <? xml version = "1.0" ?> < config > < modules > < Vacancy_CMSTemplates > < version > 0 . 1 . 0 </ version > </ Vacancy_CMSTemplates > </ modules > < global > < page > < layouts > < vacancy_two_columns translate = "label" > < label > Vacancy Two - Column Layout </ label > < template > page / vacancy - 2columns . phtml </ template > < layout_handle > vacancy_two_columns </ layout_handle > </ vacancy_two_columns > </ layouts > </ page > </ global > </ config > <?xml version="1.0"?> <config> <modules> <Vacancy_CMSTemplates> <version>0.1.0</version> </Vacancy_CMSTemplates> </modules> <global> <page> <layouts> <vacancy_two_columns translate="label"> <label>Vacancy Two-Column Layout</label> <template>page/vacancy-2columns.phtml</template> <layout_handle>vacancy_two_columns</layout_handle> </vacancy_two_columns> </layouts> </page> </global> </config>

Before changes take effect we have to edit Mage_All.xml again and tell it to use the core code instead of our extension:

/app/etc/modules/Mage_All.xml

1 2 3 4 5 6 7 8 9 10 11 12 <? xml version = "1.0" ?> < config > < modules > < Vacancy_CMSTemplates > < active > true </ active > < codePool > core </ codePool > < depends > < Mage_Page /> </ depends > </ Vacancy_CMSTemplates > </ modules > </ config > <?xml version="1.0"?> <config> <modules> <Vacancy_CMSTemplates> <active>true</active> <codePool>core</codePool> <depends> <Mage_Page /> </depends> </Vacancy_CMSTemplates> </modules> </config>

Looking good! It’s also worth noting that if you wanted to quickly disable your changes, you could disable the module in the admin panel instead of removing your code. Oddly, the list of modules is conveniently dynamic! Hmph!

Go to System -> Configuration

In sidebar: Advanced -> Advanced

Now just disable it:

.. and that’s a wrap! As for me, I’m fine sticking with the extension method.

Implementing Proper Magento Template Practices

So far we only have a static layout. And one without style, no less. Let’s set up different files for the header, sidebar, content area, and footer.

Create the HTML template folder: /app/design/frontend/vacancy-package/vacancy-theme/template/page/html/

The /html/ folder will house three of the key template files for pages.

head.phtml – Contains items such as meta info, page title, CSS/JS, and so forth

header.phtml – Contains header markup such as the logo, header navigation, etc

footer.phtml – Our footer box at the bottom of the page

Our sidebar doesn’t quite fit under the /page/ templates, so we will create a new folder for the navigation. Create sidebar.phtml at the following:

/vacancy-theme/template/catalog/navigation/sidebar.phtml

Our Head – head.phtml

All the meta info, helpers, includes and styling files are quite simple to load dynamically, thanks to Magento. The code should be straightforward:

../vacancy-theme/template/page/html/head.phtml

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 < meta http - equiv = "Content-Type" content = "<?php echo $this->getContentType () ?>" /> < title > <?php echo $this -> getTitle ( ) ?> </ title > < meta name = "description" content = "<?php echo htmlspecialchars( $this->getDescription ()) ?>" /> < meta name = "keywords" content = "<?php echo htmlspecialchars( $this->getKeywords ()) ?>" /> < meta name = "robots" content = "<?php echo htmlspecialchars( $this->getRobots ()) ?>" /> < link rel = "icon" href = "<?php echo $this->getFaviconFile (); ?>" type = "image/x-icon" /> < link rel = "shortcut icon" href = "<?php echo $this->getFaviconFile (); ?>" type = "image/x-icon" /> <!-- [ if lt IE 7 ] > < script type = "text/javascript" > //<![CDATA[ var BLANK_URL = '<?php echo $this->helper(' core / js ')->getJsUrl(' blank . html ') ?>' ; var BLANK_IMG = '<?php echo $this->helper(' core / js ')->getJsUrl(' spacer . gif ') ?>' ; //]]> </script> <! [ endif ] --> <?php echo $this -> getCssJsHtml ( ) ?> <?php echo $this -> getChildHtml ( ) ?> <?php echo $this -> helper ( 'core/js' ) -> getTranslatorScript ( ) ?> <?php echo $this -> getIncludes ( ) ?> <meta http-equiv="Content-Type" content="<?php echo $this->getContentType() ?>" /> <title><?php echo $this->getTitle() ?></title> <meta name="description" content="<?php echo htmlspecialchars($this->getDescription()) ?>" /> <meta name="keywords" content="<?php echo htmlspecialchars($this->getKeywords()) ?>" /> <meta name="robots" content="<?php echo htmlspecialchars($this->getRobots()) ?>" /> <link rel="icon" href="<?php echo $this->getFaviconFile(); ?>" type="image/x-icon" /> <link rel="shortcut icon" href="<?php echo $this->getFaviconFile(); ?>" type="image/x-icon" /> <!--[if lt IE 7]> <script type="text/javascript"> //<![CDATA[ var BLANK_URL = '<?php echo $this->helper('core/js')->getJsUrl('blank.html') ?>'; var BLANK_IMG = '<?php echo $this->helper('core/js')->getJsUrl('spacer.gif') ?>'; //]]> </script> <![endif]--> <?php echo $this->getCssJsHtml() ?> <?php echo $this->getChildHtml() ?> <?php echo $this->helper('core/js')->getTranslatorScript() ?> <?php echo $this->getIncludes() ?>

Nothing here to change. Remember our page.xml layout block where we added the CSS file? That gets called with the getCssJsHtml helper. Automatic handling of meta tags is nice too.

The Header – header.phtml

Nothing too complex here – just outputting a simple welcome text. It’s set in the administration panel. Kind of useless, but let’s add it anyway:

../vacancy-theme/template/page/html/header.phtml

1 2 3 4 5 6 < div class = "logo floatLeft" > < p > Logo </ p > </ div > < div class = "welcome floatLeft" > <?php echo $this -> getWelcome ( ) ?> </ div > <div class="logo floatLeft"> <p>Logo</p> </div> <div class="welcome floatLeft"> <?php echo $this->getWelcome() ?> </div>

The Sidebar – sidebar.phtml

For the sidebar we use a Magento helper to load all the categories and then loop through them, displaying them one at a time.

First, however, you need the categories to loop through! The administration panel is easy enough to use, but make certain that the categories you create are under “Default Category” for now. After you are done you’ll see something similar:

Now for the sidebar.phtml file:

../vacancy-theme/template/catalog/navigation/sidebar.phtml

1 2 3 4 5 6 7 8 9 10 11 12 13 <?php // Load categories and loop through them $cats = $this -> getStoreCategories ( ) ; ?> < h2 > Categories </ h2 > < ul > <?php foreach ( $cats as $cat ) : ?> < li >< a href = "<?php echo $cat->getCategoryUrl ( $cat ); ?>" > <?php echo $cat -> getName ( ) ; ?> </ a > <?php endforeach ; ?> </ ul > <?php // Load categories and loop through them $cats = $this->getStoreCategories(); ?> <h2>Categories</h2> <ul> <?php foreach($cats as $cat) : ?> <li><a href="<?php echo $cat->getCategoryUrl($cat); ?>"><?php echo $cat->getName(); ?></a> <?php endforeach; ?> </ul>

If you want to learn more about helpers like getName, your best bet is to get the class name of the object and search the Magento docs, or to do some sleuthing yourself.

Something like this does famously:

1 <?php foreach ( $cats as $cat ) : echo var_dump ( $cat -> getData ( ) ) ; exit ; ?> <?php foreach($cats as $cat) : echo var_dump($cat->getData()); exit; ?>

That will output all of the data from the Varien_Data_Tree_Node object ( which I found by echoing get_class($cat) ), allowing you to easily see what data is accessible. You can get any of the data by calling the proper method. Here’s example output of the data:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 array ( 16 ) { [ "entity_id" ] => string ( 1 ) "4" [ "entity_type_id" ] => string ( 1 ) "3" [ "attribute_set_id" ] => string ( 1 ) "3" [ "parent_id" ] => string ( 1 ) "2" [ "created_at" ] => string ( 19 ) "2011-11-06 23:23:16" [ "updated_at" ] => string ( 19 ) "2011-11-06 23:23:16" [ "path" ] => string ( 5 ) "1/2/4" [ "position" ] => string ( 1 ) "1" [ "level" ] => string ( 1 ) "2" [ "children_count" ] => string ( 1 ) "0" [ "path_id" ] => string ( 5 ) "1/2/4" [ "is_active" ] => string ( 1 ) "1" [ "include_in_menu" ] => string ( 1 ) "1" [ "request_path" ] => string ( 18 ) "pokemon-cards.html" [ "name" ] => string ( 13 ) "Pokemon Cards" [ "url_key" ] => string ( 13 ) "pokemon-cards" } array(16) { ["entity_id"] => string(1) "4" ["entity_type_id"] => string(1) "3" ["attribute_set_id"] => string(1) "3" ["parent_id"] =>string(1) "2" ["created_at"] =>string(19) "2011-11-06 23:23:16" ["updated_at"] =>string(19) "2011-11-06 23:23:16" ["path"] => string(5) "1/2/4" ["position"] => string(1) "1" ["level"] => string(1) "2" ["children_count"] => string(1) "0" ["path_id"] => string(5) "1/2/4" ["is_active"] => string(1) "1" ["include_in_menu"] => string(1) "1" ["request_path"] => string(18) "pokemon-cards.html" ["name"] => string(13) "Pokemon Cards" ["url_key"] => string(13) "pokemon-cards" }

If you want the url_key data for the category “Pokemon Cards,” you’d use the following method:

1 echo $cat -> getUrlKey ( ) ; echo $cat->getUrlKey();

You’ll be diving into code like this often with Magento: the official and community documentation is often outdated or just not helpful.

The Footer – footer.phtml

The footer also contains dynamic content. We will introduce the concept of Static Blocks in this section. A static block is a block that can be edited within the administration menu. In our case we will make the footer links easily edited.

Magento has already created our footer static block for us. You may see them if you go to CMS -> Static Blocks.

../vacancy-theme/template/page/html/footer.phtml

1 2 3 4 5 6 7 < div class = "copyright floatLeft" > Copyright 2011 Base Layout </ div > <?php echo $this -> getLayout ( ) -> createBlock ( 'cms/block' ) -> setBlockId ( 'footer_links' ) -> toHtml ( ) ; ?> < div class = "clear" >& nbsp ;</ div > <div class="copyright floatLeft"> Copyright 2011 Base Layout </div> <?php echo $this->getLayout()->createBlock('cms/block')->setBlockId('footer_links')->toHtml(); ?> <div class="clear"> </div>

The syntax for getting a block from the CMS menu is easy. If you want to include a different block, just switch ‘footer_links’ with the block identifier, which you set in the edit menu for the block.

The Template File – vacancy-2columns.phtml

Now let’s bring it all together. Our template file will piece all of the phtml files we just created together.

../vacancy-theme/template/page/vacancy-2columns.phtml

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <! DOCTYPE html > < head > <?php echo $this -> getChildHtml ( 'head' ) ; ?> </ head > < body > < div id = "wrapper" > < div id = "header" > <?php echo $this -> getChildHtml ( 'header' ) ; ?> <?php echo $this -> getChildHtml ( 'test' ) ; ?> </ div > < div id = "sidebar" class = "floatLeft" > <?php echo $this -> getChildHtml ( 'sidebar' ) ; ?> </ div > < div id = "content" class = "floatLeft" > <?php echo $this -> getChildHtml ( 'content' ) ; ?> </ div > < div id = "footer" > <?php echo $this -> getChildHtml ( 'footer' ) ; ?> </ div > </ div > </ body > </ html > <!DOCTYPE html> <head> <?php echo $this->getChildHtml('head'); ?> </head> <body> <div id="wrapper"> <div id="header"> <?php echo $this->getChildHtml('header'); ?> <?php echo $this->getChildHtml('test'); ?> </div> <div id="sidebar" class="floatLeft"> <?php echo $this->getChildHtml('sidebar'); ?> </div> <div id="content" class="floatLeft"> <?php echo $this->getChildHtml('content'); ?> </div> <div id="footer"> <?php echo $this->getChildHtml('footer'); ?> </div> </div> </body> </html>

So this is fairly simple. With getChildHtml we are simply telling the layout to find the block within quotes. If you look at your page.xml file you will see that the names here correspond to the names of each block we created.

The Result

If everything went according to plan, you should have this for a homepage:

You may download the contents of /vacancy-package/ for the skin and app directory here:

vacancy-theme.zip

Continuing Forward

This is a rather long tutorial already, so we’ll stop at this point.

The first thing you should do is become more familiar with the administration panel. Change the Homepage CMS template to show text, look at configuration options, and explore as much as possible.

Next you’ll want to create templates, layout configurations, static blocks, and anything else you want to add to the theme. If you have browsed a category page by now , it wasn’t a pretty sight. You now have the time-consuming task of learning every layout file that Magento uses and properly configuring them for your needs.

A fair warning: the Magento community gives bad advice sometimes, or it’s extremely outdated. From here you absolutely must tinker with the code and experiment by yourself, in addition to asking for help on StackOverflow, #magento on Freenode, or asking directly here. Note that the Magento forums are usually fairly dead and you are unlikely to find answers there.

I made this guide as complete as I thought possible. Please comment on things I should add if you hit a stumbling block.

Good luck, and godspeed in your Magento endeavors!