XML Layout

Prerequisites

Here be dragons

XML parsing is not lenient. A single syntax error or invalid attribute can make layout compilation fail, and Magento’s frontend will break. Minor naming and structural changes between releases can easily break custom implementations if not properly managed during upgrades.

Documentating customizations in XML layout is critical. Be critical of poorly written XML.

Modifying core XML layout

The theme fallback hierarchy supports overriding any module’s layout from a custom theme. Sometimes this is appropriate. You can also add local.xml to any theme. Magento processes this file after all module XML files, which let’s you override any core layout.

Some developers use local.xml exclusively, but GravDept does not. Any changes by Magento to the core XML layouts need to be diffed, inspected, and merged regardless. This requirement is no less rigorous using local.xml than overriding a module’s layout.

The preferred approach depends on complexity and readability.

Using local.xml

Using local.xml is best for simple changes that can be written and documented in a few lines.

<default>
    <!-- GravDept: not used -->
    <remove name="footer_links" />
</default>

Using {module}.xml overrides

When customizations are significantly different from the Magento core, it’s easier to edit/read/maintain modifications by duplicating and overriding the whole file:

/app/design/frontend/{package}/{theme}/layout/{module}.xml

This would be convoluted and error-prone to maintain in local.xml because the changes are divorced from the applicable code.

GravDept usually does this for page.xml and catalog.xml (catalog_product_view handle). These modules benefit from inline commentary that’s more descriptive than Magento’s block names.

XML layout from extensions

Third-party XML layouts must be separate and easily identifiable from core code.

Many extensions suggest placing their code in the base/default theme. GravDept doesn’t do this because the working directory is the site’s unique {package}/{theme} 99% of the time. It’s not smart to keep code that modifies the core behavior “out of sight and out of mind”.

/app/design/frontend/{package}/{theme}/layout/{namespace}/{extension-name}.xml
/app/design/frontend/{package}/{theme}/layout/{namespace}_{extension-name}.xml

Naming convention

  • Namespaced by folder or underscore in filename
  • Lowercase
  • Dash-separated

Naming blocks, aliases, and templates

[todo]

Snippets

Skin CSS

Files from /skin/frontend/{package}/{theme}/.

<!-- Add CSS -->
<action method="addCss">
    <stylesheet>css/styles.css</stylesheet>
</action>

<!-- Remove CSS -->
<action method="removeItem">
    <type>skin_css</type>
    <name>css/styles.css</name>
</action>

Skin JS

Files from /skin/frontend/{package}/{theme}/.

<!-- Add JS -->
<action method="addItem">
    <type>skin_js</type>
    <name>js/scripts.js</name>
</action>

<!-- Remove JS -->
<action method="removeItem">
     <type>skin_js</type>
     <name>js/scripts.js</name>
</action>

Core JS

Files from /js/.

<!-- Add JS -->
<action method="addJs">
    <script>script/scripts.js</script>
</action>

<!-- Remove JS -->
<action method="removeItem">
     <type>js</type>
     <name>scripts.js</name>
</action>

Remove block

<remove name="welcome" />

Note: blocks cannot be removed, then added elsewhere in the layout. Use unset instead.

Move block

<!-- Unset the block -->
<reference name="left">
    <action method="unsetChild">
        <name>left.newsletter</name>
    </action>
</reference>

<!-- Insert the block elsewhere -->
<reference name="footer">
    <action method="insert">
        <block>left.newsletter</block>
    </action>
</reference>

Set root template

<reference name="root">
    <action method="setTemplate">
        <template>gravdept/page/custom-name.phtml</template>
    </action>
</reference>

Add <body> class

<reference name="root">
    <action method="addBodyClass">
        <className>the-class-name</className>
    </action>
</reference>

Resources