Template engines
Exponential 6.0.15 renders templates in three languages. All three run inside the same template system: they are found through the same design chain and override rules, see the same variables, can call every operator, fetch function and template function, and can include each other, so one design and even one page can mix them. The engine is chosen by the file ending.
| Exponential templates | Smarty templates | Twig templates | |
|---|---|---|---|
| File ending | .tpl | .stpl | .twig, .html.twig |
| Language | Exponential's own | Smarty 5 | Twig 3 |
| Settings | site.ini [TemplateSettings], template.ini | smarty.ini [SmartySettings] | twig.ini [TwigSettings] |
| Code | lib/eztemplate | lib/smarty | lib/twig |
| Include | {include uri='design:x.tpl'} | {expinclude uri='design:x.tpl'} | {% expinclude uri='design:x.tpl' %} |
| Cache block | {cache-block} | {expcacheblock} | {% expcacheblock %} |
| Escaping | wash | wash (no automatic escaping) | wash (no automatic escaping by default) |
| Sandbox | the template system's rules | Smarty's security policy, on by default | Twig's sandbox, on by default |
Nothing has to be switched on: Smarty and Twig templates work in every siteaccess. The file endings and their renderers are registered in site.ini [TemplateBridgeSettings] EngineSuffixList[] and RendererList[]. Which engines and library versions your installation has:
./console exp:template:engines
It prints one line per engine with its version, its endings, its settings and where it stores compiled templates, and ends with PASS 3 engines available.
Using a Smarty or Twig template
The code of the kernel asks for .tpl templates, such as node/view/full.tpl. A template of another engine is used where an override rule names it, or where a template includes it by name:
[full_article_twig] Source=node/view/full.tpl MatchFile=full/article.twig Subdir=templates Match[class_identifier]=article
{# design/example/override/templates/full/article.twig #}
<h1>{{ node.name|wash }}</h1>
{{ attribute_view_gui({attribute: node.data_map.body}) }}
{% for child in fetch('content', 'list', {parent_node_id: node.node_id, limit: 3}) %}
{{ node_view_gui({content_node: child, view: 'line'}) }}
{% endfor %}
The same in Smarty, as full/article.stpl:
<h1>{$node.name|wash}</h1>
{attribute_view_gui attribute=$node.data_map.body}
{$children = fetch('content', 'list', ['parent_node_id' => $node.node_id, 'limit' => 3])}
{foreach $children as $child}
{node_view_gui content_node=$child view='line'}
{/foreach}
The standard design ships a Smarty example in design/standard/templates/smarty/ (demo_full.stpl and demo_children.stpl); its first line says how to switch it on with an override rule. Includes work in every direction: {include uri='design:parts/menu.twig'} in a .tpl, {expinclude uri='design:parts/menu.tpl'} in a .stpl, {% expinclude uri='design:parts/menu.stpl' %} in a .twig.
Which to choose
- .tpl for existing designs and for developers who know Exponential: every shipped design and extension uses it, and every example in this manual.
- .stpl for a team that knows Smarty, or a design that comes from a Smarty project.
- .twig for a team that knows Twig from Symfony, Drupal or Craft, or templates shared with such a project. Twig templates can use inheritance ({% extends %}, {% block %}) and macros.
Speed does not decide it: cached pages do not reach a template engine, and uncached pages render within a small margin of each other; the measurements are in Speed of the three template engines.
Converting a design
The converters turn the templates of a design into another engine, in every direction, and check each result before writing it:
./console exp:template:convert --from-engine=tpl --to-engine=twig --from=extension/myext/design/example --to=var/tmp/example_twig --dry-run ./console exp:template:convert:tpl-to-stpl --from=extension/myext/design/example --to=var/tmp/example_stpl ./console exp:template:convert:diff --help
The named commands are exp:template:convert:tpl-to-stpl, :stpl-to-tpl, :tpl-to-twig, :twig-to-tpl, :stpl-to-twig and :twig-to-stpl; each also exists as a script in bin/php/ (exptemplateconverttpltotwig.php and so on). Every written file ends with a marker comment, so a second run replaces only files it wrote and nobody changed since; constructs that cannot be converted exactly are reported as NOTE. See Converting templates between template engines.
Checking the syntax
./console exp:template:check (also php bin/php/exptemplatecheck.php) checks templates of all three engines, each with its own parser and compiler, without writing anything: a file, a folder, a design or the design chain of a siteaccess. See Debugging templates and Checking template syntax.
Further reading
- The three template engines compared
- Twig templates and its guides: tutorial, operators, caching, security, recipes
- Smarty templates and its guides
- Templates side by side: one template in all three languages
Both engines were added to Exponential in October 2026 and are part of 6.0.15.
Contributors
- Graham Brookins Updated Maintainer
Comments
Add a comment