Skip to the content
Documentation

Template engines

No ratings yet

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

Both engines were added to Exponential in October 2026 and are part of 6.0.15.

Contributors

Comments

Add a comment

Comments are read by a moderator before they appear.