Guide 02 · Developer docs

Template languages: Smarty and Twig

Core dna renders server-side sites with Smarty or with Twig, one engine per site, and treats the two as peers. This guide is the one place both are documented: what they share, each engine's language and the platform's additions and limits, the two side by side, and translation.

L1–L2
Unit 02 · Smarty

Smarty in Core dna

Core dna runs Smarty 4.4 with braces as delimiters, a security policy that cannot be switched off, a handful of plugins of its own, and no automatic escaping. How the platform configures it, how to check a site's delimiters, why records are objects, and where errors and debug output show.

Who this is for. The developer starting on a Smarty site, whether new to Smarty or to Core dna. Afterwards you will know what the platform changes about stock Smarty, which page of this unit covers each part, and how to see what went wrong when a template fails.

How the platform configures Smarty

SettingOn Core dnaRead more
VersionSmarty 4.4The upstream Smarty 4 manual applies, within the limits below
Delimiters{ and }, from the site settings Globals.template.smarty.leftDelimiter and rightDelimiterBelow
Security policyAlways on: a list of callable PHP functions, a much shorter list of PHP functions usable as modifiers, no super-globals, files only from the template foldersThe template security policy
EscapingNone by default: {$value} prints the value as it isEscaping
Platform pluginsTranslation tags, |format, {json}, {error}, {debug_vars} and four modifiersWhat the platform adds to Smarty
Compiled templatesKept per site on production and checked against the file; recompiled on every request elsewhereCompilation and caching
Output cachingSmarty's own caching is off; the platform's page cache does that jobThe caching tiers

The language itself is covered in Smarty syntax: output, assignment and control flow, and inheritance and includes in Smarty inheritance, includes and the template context.

Check the delimiters before you write anything

The delimiters are settings rather than constants. Every site that has not changed them uses braces, and every example in this documentation assumes braces. A site can change them in the .settings.json at the root of its site folder, under Globals.template.smarty; if your repository has that file, read it before writing a template. The quicker check is any existing template: whatever wraps $page is the site's delimiter.

The delimiters apply to every template the site renders, including the platform's own sign-in page and message partials, which are written with braces. A site that changes them has to override every platform template it uses.

Smarty's auto-literal rule is on: a { followed by a space, a tab or a line break is printed as it is. CSS and JavaScript written with a space after each brace need no special treatment; anything else that contains braces goes inside {literal}:

Template code Smarty only
<style>.card { padding: 1rem; }</style>   {* a brace followed by a space: printed as it is *}

{literal}
<script type="application/ld+json">{"@context":"https://schema.org","@type":"Organization"}</script>
{/literal}

{ldelim}not a tag{rdelim}   {* prints {not a tag} *}

An inline <script> also needs nonce="{$_inlineScriptNonce}" or the browser refuses it; inside {literal} the variable is not replaced, so keep the opening tag outside the literal block when the script needs one.

Records are objects, data is arrays

Smarty has two access syntaxes, and on Core dna they are not interchangeable. A record is an object, reached with -> and its methods. An array, such as the parameters you pass to an include or the result of json_decode(), is reached with a dot or square brackets.

Template code Smarty only
{$page->getName()}                {* a record: call its method *}
{$page->getAllParents()|count}    {* chained with a modifier *}

{$page.name}                      {* fatal error: Cannot use object of type … as array *}

{$sizes = ['width' => 800, 'data-ratio' => '4:3']}
{$sizes.width}                    {* an array: dot *}
{$sizes['data-ratio']}            {* square brackets for a key with a hyphen *}

What a record lets you call is fixed per record type: Response models. A key with a hyphen needs square brackets because {$sizes.data-ratio} is read as a subtraction.

Where errors show

What went wrongWhat you see on a development environmentWhat a visitor sees on production
Syntax error, or a function or modifier the policy refusesA stack-trace page whose message names the template, the line and the problem, such as modifier 'trim' not allowed by security settingThe site's errors/fatal-error.html, or the platform's plain error page if the site has none
A method the record does not offer, or an error raised while renderingThe same stack-trace pageThe same error page
An undefined variable or array keyThe page renders, with nothing where the value would beThe same; the warning is written to the site's log with the template's name, on every view

Errors that come from a template are logged with the template's file name rather than the compiled file's line, so search the log for the template you suspect. A template with a syntax error fails on every request, so a broken deploy shows at once; an undefined variable never fails, and only the log shows it.

Debugging

  • See what the controller passed. On a development environment, add ?dev=1 to the URL: a panel at the foot of the page lists the controller's variables. On production the panel appears only to a signed-in backend user of type developer.
  • Dump a value you choose. {debug_vars page=$page items=$items} adds the values to the same panel on a development environment and does nothing anywhere else, so it is safe to leave in.
  • Fail loudly on purpose. {error message='Hero image missing'} stops the render with that message, which beats a page that renders half a component.
  • Never commit |dd. It is allowed by the policy, prints the value, sends a 500 and ends the request on any environment, production included.

All three platform functions are described in What the platform adds to Smarty.

Go deeper

Was this page helpful?

Your answer goes to the docs team.