Building a website switcher module for Magento

Mar 25, 2011

magento store switcher

I recently had to build a module for Magento that let you switch between each of the Magento Websites in the admin. I’ve written a short explanation of how I did this below, along with the code.

Create a module

First off, you need a name for your company/organisation and a name for your module. Once you decide that you need to create the folders. You will probably want to put your module on the local scope – this is where I do everything, although if you are developing a plugin then people sometimes use the community scope. Anyway, you need to create the following folder structure.

siteroot/
   app/
      code/
         local/
            Organisation/
               ModuleName/
                  Block/
                  etc/

The siteroot/app/code/local/ folders should already exist. You then need to create a simple config file for your module, this will be a file called config.xml inside the etc folder – and it should contain the following xml.

<?xml version="1.0"?>
<config>
   <modules>
      <Organisation_ModuleName>
         <version>1.0.0</version>
      </Organisation_ModuleName>
   </modules>
   <global>
      <blocks>
         <modulename>
            <class>Organisation_ModuleName_Block</class>
         </modulename>
      </blocks>
   </global>
</config>

You may notice that in some places in the file structure and xml the case of the organisation and modulename references change. This is important to get right (I think!).

So what we are doing with xml is telling Magento that we have a module of version 1.0.0 and it has a block that is implemented in the class Organisation_ModuleName_Block. Now the naming of these things is slightly odd and I have yet to really work out the logic behind it all but you will see that the names are really important as is the use of the word Block, in the folder structure and the class names – so when you rewrite this with your own module names make sure you don’t accidently lose anything as you cut, paste and replace.

Now before we actually put any code into the Block folder we need to activate the module. I know, I know – surely the fact that the folders exist and there is a config file could and should be enough – but Magento is a strange beast and you need another xml file…

siteroot/
   app/
      etc/
         organisation.xml

The file can be named anything and allows you list one or more modules, explaining where the code is (local, community or core) and flagging them as active or inactive. I suppose the point of this is the ability to override modules with your own versions and turn functionality on and off in one place. So maybe it is quite useful after all. The file should contain the following…

<?xml version="1.0"?>
<config>
   <modules>
      <Organisation_ModuleName>
         <active>true</active>
         <codePool>local</codePool>
      </Organisation_ModuleName>
   </modules>
</config>

Put some code in your module

I initially spotted that the existing Magento currency switcher and store switcher both use a Block from the core Page module called Switch.php. Now I probably could have just used this class and created a new template phtml file that switches between websites since my template (as you will see a bit later) actually doesn’t use any code from my modules block. I will explain here what I have done, and mention what I should have done as well – I may refactor my code at some point but sometimes speed is of th essence.

I have taken a complete copy of the existing Switch.php file and placed it in my modules Block subfolder, then renamed it Websites.php. I then changed the class name to match the class I have already specified in the config files. Again, watch out for these as they are all subtle variations of the same names. The class definition should be as follows…

class Organisation_ModuleName_Block_Websites extends Mage_Core_Block_Template

Notice the class contains the word Block which refers to the folder it is in (I think) and also Websites which refers to the name of the file it is in (I think).

Now to write this in a better way you could subclass the original Switch.php – or simply copy the code into your new class. Either way you could (and probably should) write methods to read the Magento Websites in the same way that the current class reads Stores and Groups. The benefit of doing this is that the template I am about to explain could contain less code that directly gets data from Magento and thus would be more flexible in the future.

Quick note: Magento refers to Stores as StoreGroups in the database and code, and StoreViews as Stores.

Build a template

Next thing you need to do is build a template for your module, you need to create a folder in your designs template folder with the same name as your module. It actually doesn’t really matter and I found it simpler to create my template in the templates/page/switch folder along side the similar switchers for currency and languages. I was also pretty lazy here and wrote the code directly in the template instead of separating it a little more with the code in the module and display in the template – again, this is up to your own conscience.

I have done this with flag images for each site but this could easily be changed to be a html select element, text links in a ul or other images. The code for the template is shown below.

<?php $websites=Mage::app()->getWebsites();?>
<?php if(count($websites)>1): ?>
<div class="store-switcher icon-switcher">
   <?php
   $url_obj = new Mage_Core_Model_Url();
   $current_store_path = $url_obj->getBaseUrl(array('_store'=> Mage::app()->getStore()));
   foreach ($websites as $website):
      $default_store = $website->getDefaultStore();
      $default_store_path = $url_obj->getBaseUrl(array('_store'=> $default_store->getCode())); ?>
         <a href="<?php echo $default_store_path ?>"<?php if($current_store_path == $default_store_path):?>class="selected"<?php endif; ?>>
         <img src="<?php echo $this->getSkinUrl('images/flags/'.$this->htmlEscape($website->getName()).'.png') ?>" alt="<?php echo $this->htmlEscape($website->getName()) ?>" />
         </a>
      <?php endforeach; ?>
</div>
<?php endif; ?>

Place the template in your design

One final step and you should be there. You just need to place your template/module onto your design somewhere. Normally I would put this into the header of your page, which can be done by adding a line to your page layout xml file and a line in the template/page/html/header.phtml file.

For the page layout, you need to insert the following line inside the header block (look for name=”header”) inside the default page layout (look for <default and name=“root”).

<block type="modulename/websites" name="name_for_this_block" as="name_for_this_block" template="page/switch/websites.phtml"/>

On its own this won’t do anything, you also need to modify the html/header.phtml to ask for the template for the “name_for_this_block”. Just add the following line to the header.phtml wherever you want and the template will be evaluated and inserted.

<?php echo $this->getChildHtml('name_for_this_block') ?>

And finally, just to prove it is possible – a screenshot of the module in action…

website switcher