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>