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
SmartyPage 9 of 25Updated
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
Setting
On Core dna
Read more
Version
Smarty 4.4
The upstream Smarty 4 manual applies, within the limits below
Delimiters
{ and }, from the site settings Globals.template.smarty.leftDelimiter and rightDelimiter
Always 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 folders
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 codeSmarty 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 codeSmarty 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 wrong
What you see on a development environment
What a visitor sees on production
Syntax error, or a function or modifier the policy refuses
A stack-trace page whose message names the template, the line and the problem, such as modifier 'trim' not allowed by security setting
The 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 rendering
The same stack-trace page
The same error page
An undefined variable or array key
The page renders, with nothing where the value would be
The 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.