The layout of Magento’s information, warning and error messages cannot be easily changed using layout and template files. The HTML generation is done from a Block PHP class (Mage_Core_Block_Messages). It is a very bad idea to overwrite any core element of Magento. Instead we are going to extend this core-block by creating a separate module.

Bootstrap Alerts in Magento
Messages are now Bootstrap compatible

My goal was to make the messages compliant with Twitter Bootstrap alerts but the following technique can be used for about anything.

From inspection of ‘app/code/core/Mage/Core/Block/Messages.php’ it can be seen how Magento generates the HTML of the various messages. See for example the ‘getHtml’-method

/**
 * Retrieve messages in HTML format
 *
 * @param   string $type
 * @return  string
 */
public function getHtml($type=null)
{
    $html = '<' . $this->_messagesFirstLevelTagName . ' id="admin_messages">';
    foreach ($this->getMessages($type) as $message) {
        $html.= '<' . $this->_messagesSecondLevelTagName . ' class="'.$message->getType().'-msg">'
            . ($this->_escapeMessageFlag) ? $this->escapeHtml($message->getText()) : $message->getText()
            . '</' . $this->_messagesSecondLevelTagName . '>';
    }
    $html .= '</' . $this->_messagesFirstLevelTagName . '>';
    return $html;
}

Most parts of the HTML are variable which allows easy overwriting by extending the original core-block.

Structure of the module

The structure of the module will be as shown below. It will be implemented as a modman module to allow for separation of our module code from the Magento installation.

├── modman
└── src
    └── app
        ├── code
        │   └── local
        │       └── MyBrand
        │           └── MessagesBlock
        │               ├── Block
        │               │   └── Messages.php
        │               └── etc
        │                   └── config.xml
        └── etc
            └── modules
                └── MyBrand_MessagesBlock.xml

There are four files in this module.

  • modman file contains a list of how the various folders should be symlinked to your Magento installation.
  • Messages.php will extend Magento’s core PHP block
  • config.xml will instruct Magento to use our Messages.php Block instead of Magento’s core one
  • MyBrand_MessagesBlock.xml is the module xml-file that tells Magento about the existence of our module

Module XML-file

Let’s start bottom-up. Create the MyBrand_MessagesBlock.xml (or whatever you would like to call it) and fill it up with the following XML.

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

It will tell Magento of the existence of a module named ‘MyBrand_MessagesBlock’ that is active and located in the ‘local’ code pool.

Module Config-file

The Module Config-file is an XML-file too. Create an empty config.xml at the right location with the following content

<?xml version="1.0"?>
<config>
    <modules>
        <MyBrand_MessagesBlock>
            <version>1.0.0</version>
        </MyBrand_MessagesBlock>
    </modules>
    <global>
        <blocks>
            <core>
                <rewrite>
                    <messages>MyBrand_MessagesBlock_Block_Messages</messages>
                </rewrite>
            </core>
        </blocks>
    </global>
</config>

This tells Magento about the version of the module. It also directs Magento to rewrite (relocate) the Block-code file ‘messages’ from the ‘core’ package. This is structured in the XML-file as follows

  1. **** Configuration
  2. **** Global configuration
  3. **** Applies to (block, model, etc.)
  4. **** Package (core, cms, customers, etc.)
  5. **** What to configure
  6. **** What block of this package to rewrite
  7. MyBrand_MessagesBlock_Block_Messages The full name of the replacement class

Overwrite Messages.php

This is the Block-code file that will extend the original class and overwrite whatever we want. In this case I changed the first- and second-level tag names and the behaviour of the ‘getGroupedHtml’ method so that it fits well with Twitter Bootstrap. Create it and write your own code. You can use the following as a guide.

<?php
class MyBrand_MessagesBlock_Block_Messages
    extends Mage_Core_Block_Messages
{

    protected $_messagesFirstLevelTagName   = 'div';
    protected $_messagesSecondLevelTagName  = 'div';


    /**
     * Retrieve messages in HTML format grouped by type
     *
     * @param   string $type
     * @return  string
     */
    public function getGroupedHtml()
    {
        $types = array(
            Mage_Core_Model_Message::ERROR,
            Mage_Core_Model_Message::WARNING,
            Mage_Core_Model_Message::NOTICE,
            Mage_Core_Model_Message::SUCCESS
        );

        $twbs_types = array(
            Mage_Core_Model_Message::ERROR => 'danger',
            Mage_Core_Model_Message::WARNING => 'warning',
            Mage_Core_Model_Message::NOTICE => 'info',
            Mage_Core_Model_Message::SUCCESS => 'success'
        );

        $html = '';
        foreach ($types as $type) {
            if ( $messages = $this->getMessages($type) ) {
                if ( !$html ) {
                    $html .= '<' . $this->_messagesFirstLevelTagName . ' class="messages">';
                }

                $html .= '<' . $this->_messagesSecondLevelTagName . ' class="alert alert-' . $twbs_types[$type] . '">';
                $html .= '<' . $this->_messagesFirstLevelTagName . '>';

                foreach ( $messages as $message ) {
                    $html.= '<' . $this->_messagesSecondLevelTagName . '>';
                    $html.= '<' . $this->_messagesContentWrapperTagName . '>';
                    $html.= ($this->_escapeMessageFlag) ? $this->escapeHtml($message->getText()) : $message->getText();
                    $html.= '</' . $this->_messagesContentWrapperTagName . '>';
                    $html.= '</' . $this->_messagesSecondLevelTagName . '>';
                }
                $html .= '</' . $this->_messagesFirstLevelTagName . '>';
                $html .= '</' . $this->_messagesSecondLevelTagName . '>';
            }
        }
        if ( $html) {
            $html .= '</' . $this->_messagesFirstLevelTagName . '>';
        }
        return $html;
    }

}

Modman file

Eventually, create the ‘modman’ file to enable easy deployment of your newly created module.

src/app/code/local/MyBrand/MessagesBlock     app/code/local/MyBrand/MessagesBlock
src/app/etc/modules/MyBrand_MessagesBlock.xml	app/etc/modules/MyBrand_MessagesBlock.xml

How to deploy

The module can now be deployed by installing modman and running the following command:

modman init
modman link modules/path_to_module
modman deploy

If you are on Windows you could either use the unofficial PHP clone of modman or manually copy the module files to your installation (unfortunately polluting your installation a bit).

Conclusion

As you get more used to the quite complex structure of Magento its powerful flexibility will become apparent. This method is applicable to many situations in which you would like to change or improve core functionality of Magento.