Smarty and the template language: the differences in depth
The side-by-side table shows where the two languages match. This page takes the places where they do not, explains each from the code of the template engine and shows what happens on a development installation when a Smarty habit meets the template language.
Exponential runs Smarty templates itself: a design can hold Smarty 5 templates (
.stpl) next to its.tpltemplates, with every operator, fetch function, template function, override rule and cache of the template system. If you would rather keep writing Smarty, see Smarty templates (.stpl) next to .tpl and Moving from .tpl to .stpl, which also converts templates in both directions.
Contents
- No infix arithmetic
- No infix comparison
- Operators instead of symbols
- No automatic escaping
- Unknown operators pass their input through
- def and set are strict
- Braces in CSS and JavaScript
- No PHP in templates
- Operators and functions are registered PHP classes
- Data comes from fetch, and values are objects
- Overrides instead of inheritance
- Namespaces
- Whitespace around tags
- Related pages
No infix arithmetic
The expression parser (parseVariableTag() in lib/eztemplate/classes/eztemplateelementparser.php) knows values,
variables, attribute lookups (. and [ ]), operators (name( or |name) and nothing else. A + is not part of the
language. It reads the number 1, finds characters it cannot use, logs a parser error and prints what it had:
[{1+2}]Output:
[1]Logged by the template engine:
ERROR : parser error @ tl-diff/01-no-infix-arithmetic.tpl:1[2]
Extra characters found in expression, they will be ignored.
+2' (1)No infix comparison
The same goes for >, <, ==, && and ||. In an {if} the condition parser stops after $a, the rest is
reported as invalid, and the condition that is actually tested is only $a. With $a = 0 that is false, so the
template prints "not greater", but only by accident: with $a = 1 the same tag would print "greater" although 1 is
not greater than 1.
def $a = 0
[if $a > 1greaterelsenot greater/if]Output:
[not greater]Logged by the template engine:
ERROR : parser error @ tl-diff/02-no-infix-comparison.tpl:2[7]
Invalid parameter characters in function 'if': '> 1'Operators instead of symbols
Every calculation and comparison is an operator, either called or piped: sum, sub, mul, div, mod, inc,
dec; eq, ne, gt, ge, lt, le; and, or, not. They nest freely:
def $a = 0
[sum( 1, 2 )] [{1|sum( 2 )}] [mul( 3, 4 )] [{10|sub( 4 )}]
[if $a|gt( 1 )greaterelsenot greater/if]
[if and( $a|ge( 0 ), $a|lt( 10 ), not( $a|eq( 5 ) ) )in range/if]Output:
[3] [3] [12] [6]
[not greater]
[in range]No automatic escaping
Output is never escaped by the engine. What a variable holds is written as it is, so text from content, URLs or
request parameters must be passed through wash (or another escaping operator) where it is printed:
def $text = '<script>alert(1)</script> & "quotes"'
raw: $text
washed: $text|washOutput:
raw: <script>alert(1)</script> & "quotes"
washed: <script>alert(1)</script> & "quotes"Attributes of content objects that are already HTML, such as the output of a rich text field, are printed through their
view templates (attribute_view_gui) and must not be washed a second time. See
Wash and escaping.
Unknown operators pass their input through
Smarty fails to compile a template that uses an unknown modifier. The template language logs a warning ("Operator '...' is not registered") and leaves the value as it was. A misspelled operator therefore does not stop the page; it silently does nothing, so read the debug output:
['unchanged'|nosuchoperator]Output:
[unchanged]Logged by the template engine:
WARNING : Operator 'nosuchoperator' is not registereddef and set are strict
{def} creates a variable and warns if it exists already (it then assigns the value anyway); {set} changes a variable
and refuses to create one. Both write a warning, not an error, so the page renders on:
def $color = 'red'
def $color = 'blue'
set $size = 'large'
[$color]Output:
[blue]Logged by the template engine:
WARNING def: Variable 'color' is already defined.
WARNING set: Variable 'size' doesn't exist, cannot setThe rules come from eZTemplateDefFunction::process() and eZTemplateSetFunction::process(); see
Variables in depth.
Braces in CSS and JavaScript
Any { starts a tag. A CSS rule or a JavaScript object in a template is parsed as a tag named after whatever follows
the brace, which is an error, and everything after it is lost. Here even the word "after" disappears:
before
.box { color: red; }
afterOutput:
before
.boxLogged by the template engine:
ERROR : parser error @ tl-diff/07-braces-in-text.tpl:2[11]
Invalid parameter characters in function '': ': red; '
WARNING : Function "" is not registeredThe fixes are the same as in Smarty: {literal}...{/literal} around the block, or {ldelim} and {rdelim} for single
braces. In Exponential's admin designs scripts and styles do not belong in templates at all; they live in files loaded
through the design's script and style lists.
before
literal.box { color: red; }/literal
.box ldelim color: red; rdelim
afterOutput:
before
.box { color: red; }
.box { color: red; }afterNo PHP in templates
There is no {php} tag. The parser treats it as a function name, the engine has no such function, and the block is
dropped with a warning:
[phpecho 1;/php]Output:
[]Logged by the template engine:
WARNING : Function "php" is not registeredLogic that needs PHP goes into an operator, a function or a fetch function of an extension.
Operators and functions are registered PHP classes
A Smarty plugin is a PHP function found by its file name. A template operator is a method of a class that an
eztemplateautoload.php file lists ($eZTemplateOperatorArray); the engine reads those lists from the paths in
site.ini [TemplateSettings] AutoloadPathList and from every extension named in ExtensionAutoloadPath
(eZTemplate::factory() and eZTemplate::autoload()). The class is loaded the first time one of its operators is used.
Template functions are registered the same way through $eZTemplateFunctionArray. The two are compared in
Functions versus operators.
Data comes from fetch, and values are objects
A Smarty template usually receives all its data from the PHP that renders it. A template of Exponential often asks for
data itself: fetch( 'content', 'list', hash( ... ) ) runs a fetch function of the content module, with the
permissions of the current user. The values are PHP objects (nodes, content objects, attributes) read through
attribute(): $node.data_map.title.content. See Attribute access and
Fetch basics.
Overrides instead of inheritance
Smarty templates extend each other with {extends} and {block}. In Exponential the pagelayout wraps every page and
prints the result of the module view ($module_result.content), and the override system (override.ini) chooses
which template renders a view by class, section, node, parent, view mode and more. Parts of a page are shared with
include and the *_view_gui functions. See Override basics.
Namespaces
Variables live in namespaces. An include without a name runs in the namespace of the caller and sees all its
variables; with name='box' it runs in its own namespace and sees only the parameters it was given. section and
let with a name create namespaces too. See Namespaces.
Whitespace around tags
The parser removes one newline directly before and one directly after every function tag ({if}, {/foreach},
{def ...}), but not around output tags such as {$x}. Templates can therefore put each function on its own line
without adding blank lines to the HTML. See Lexical structure.
Related pages
- Moving from Exponential templates (.tpl) to Exponential Smarty templates (.stpl) and Smarty templates (.stpl) next to .tpl: Smarty templates run by Exponential itself
- Previous: Smarty and the template language side by side
- Next: Moving a template from Smarty
- Common template mistakes
- Logic and comparison operators
- Literal and delimiters
- 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.