Templates and overrides for CMS developers
This page is for developers who build the presentation of a site. It gives the whole mechanism in one place and sends you to the designers' and the book's pages for the details. If you only remember one thing: you never edit a shipped template; you add a template of your own and a rule that says when to use it.
Contents
- How a page is drawn
- The design chain
- Override rules
- The template language in ten lines
- Where your templates live
- Finding the template behind a page
- Rules for maintainable templates
- Where to go deep
How a page is drawn
Request -> siteaccess -> module/view (content/view/full/61)
view template: node/view/full.tpl -> override rule -> full/exp_event.tpl -> $module_result.content
pagelayout.tpl wraps it: <html>, header, menus, footer, {$module_result.content}Every page is the result of a view, drawn by a view template, placed inside the pagelayout (pagelayout.tpl),
the outer template of the design. The pagelayout receives the view's result as $module_result with the content, the
path and information about the node (The pagelayout,
Module result and content info). Pages built with
Exponential Layouts add zones and blocks to this picture (Layouts for CMS developers).
The design chain
A template path such as node/view/line.tpl is searched in a chain of designs: the siteaccess's SiteDesign, then
AdditionalSiteDesignList[], then the standard design, each also inside every active extension that has a design/
folder for it. The first match wins. That is how your design extension's templates win over the shipped ones without
touching them (The design chain,
The design cascade).
Override rules
For content, the chain alone is not enough: an article and an event both use node/view/full.tpl. Override rules in
override.ini choose a different file by condition:
[exp_mysite_full_event]
Source=node/view/full.tpl
MatchFile=full/exp_event.tpl
Subdir=templates
Match[class_identifier]=exp_event
Priority=10The match keys are class_identifier, class, node, parent_node, parent_class_identifier, object,
remote_id, section, section_identifier, depth, url_alias, viewmode and view_offset; all conditions of a
rule must match, and the first matching rule in order wins
(Override basics, Override match keys,
Override ordering). Match on identifiers, not on numeric IDs, when a rule
must work on every installation; remote_id is the stable way to target one object.
The template language in ten lines
{* a comment *}
def $children = fetch( 'content', 'list', hash( 'parent_node_id', $node.node_id, 'limit', 5 ) )
if $children|count()
<ul>
foreach $children as $child
<li>node_view_gui content_node=$child view='line'</li>
/foreach
</ul>
/if
undef $children
<p>$node.data_map.intro.content|wash()</p>Functions use braces ({if}, {foreach}, {def}, {include}), operators are piped (|wash(), |ezurl,
|count()), and templates have no access to PHP: anything they need comes from fetch functions, operators and
variables. wash escapes output; use it on everything you print that is not already HTML from a datatype
(What the template language is,
Template operators). If you know Smarty, read
Smarty side by side.
Where your templates live
In your design extension, never in design/standard or another shipped design:
extension/exp_mysite/
design/exp_mysite/templates/pagelayout.tpl your pagelayout
design/exp_mysite/templates/node/view/line.tpl a default for a view mode
design/exp_mysite/override/templates/full/exp_event.tpl a template chosen by a rule
design/exp_mysite/stylesheets/ ... javascript/ ... images/
settings/design.ini.append.php registers the design in the extension
settings/siteaccess/<public siteaccess>/override.ini.append.php the rulesTemplates hold no <style> block and no style="" attribute; CSS goes into stylesheets loaded through
[StylesheetSettings] (No inline CSS). Building the extension step by
step: Your own design extension.
Finding the template behind a page
On a development installation:
./console exp:ini set site.ini/TemplateSettings/ShowUsedTemplates enabled global --allow-root-user
./console exp:ini set site.ini/TemplateSettings/ShowTemplatePathComments enabled global --allow-root-user
php bin/php/ezcache.php --clear-tag=ini --allow-root-userThe debug output then lists every template a page used and the override rule that chose it, and the page source
names the template of each part in HTML comments
(Finding the template behind a page,
Template path comments). Check a template's syntax from the shell
with ./console exp:eztemplatecheck --help.
Rules for maintainable templates
- One template per class and view mode; shared parts in
{include}files. - Fetch in the view template, not in the pagelayout, unless the data is the same on every page (menus), and then in a cache block (Caching for CMS developers).
- Print only washed values or datatype output; never build HTML from user input by concatenation.
- Use
i18nfor fixed strings (Translations and languages). - Keep business logic in operators or fetch functions of your extension, not in long template conditions (Template style guide).
Where to go deep
| Topic | Page |
|---|---|
| The language, completely | The template language |
| Every operator | Template operators |
| Designers' template reference | Templates overview |
| The builder's chapter | Templates for builders |
| The course | Module 2: The template language |
Related pages
- View modes
- Fetching content in templates
- Templates and design: the administrator's guide
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.