Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

Smarty and the template language: the differences in depth

The differences that trip up Smarty users, each shown on a development installation - no infix arithmetic or comparison, no PHP in templates, no automatic escaping, unknown operators that pass their input through…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/help/template-language/smarty-differences-in-depth.md

On this page

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 .tpl templates, 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

  1. No infix arithmetic
  2. No infix comparison
  3. Operators instead of symbols
  4. No automatic escaping
  5. Unknown operators pass their input through
  6. def and set are strict
  7. Braces in CSS and JavaScript
  8. No PHP in templates
  9. Operators and functions are registered PHP classes
  10. Data comes from fetch, and values are objects
  11. Overrides instead of inheritance
  12. Namespaces
  13. Whitespace around tags
  14. 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 > 1}greater{else}not 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 )}greater{else}not 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|wash}

Output:

raw:    <script>alert(1)</script> & "quotes"
washed: &lt;script&gt;alert(1)&lt;/script&gt; &amp; &quot;quotes&quot;

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 registered

def 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 set

The 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; }
after

Output:

before
.box

Logged 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 registered

The 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}
after

Output:

before
.box { color: red; }
.box { color: red; }after

No 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:

[{php}echo 1;{/php}]

Output:

[]

Logged by the template engine:

WARNING : Function "php" is not registered

Logic 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.

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.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x