Latte Tags
Summary and description of all Latte built-in tags.
{$var} , {...} or {=...} |
prints an escaped variable or expression |
{$var|filter} |
prints with filters |
{l} or {r} |
prints { or } character |
{if} … {elseif} … {else} … {/if} |
condition if |
{ifset} … {elseifset} … {/ifset} |
condition ifset |
{ifchanged} … {/ifchanged} |
test if there has been a change |
{switch} {case} {default} {/switch} |
condition switch |
n:else |
alternative content for conditions |
{foreach} … {/foreach} |
foreach |
{for} … {/for} |
for |
{while} … {/while} |
while |
{continueIf $cond} |
continue to next iteration |
{skipIf $cond} |
skip the current loop iteration |
{breakIf $cond} |
breaks loop |
{exitIf $cond} |
early exit |
{first} … {/first} |
is it the first iteration? |
{last} … {/last} |
is it the last iteration? |
{sep} … {/sep} |
will next iteration follow? |
{iterateWhile} … {/iterateWhile} |
structured foreach |
$iterator |
special variable inside foreach loop |
{include 'file.latte'} |
includes a template from other file |
{sandbox 'file.latte'} |
includes a template in sandbox mode |
{block} |
anonymous block |
{block blockname} |
block definition |
{define blockname} |
block defintion for future use |
{include blockname} |
prints block |
{include blockname from 'file.latte'} |
prints a block from file |
{import 'file.latte'} |
loads blocks from another template |
{layout 'file.latte'} / {extends} |
specifies a layout file |
{embed} … {/embed} |
loads the template or block and allows you to overwrite the blocks |
{ifset blockname} … {/ifset} |
condition if block is defined |
{try} … {else} … {/try} |
catching exceptions |
{rollback} |
discards try block |
{var $foo = value} |
variable creation |
{default $foo = value} |
default value when variable isn't declared |
{parameters} |
declares variables, types a default values |
{capture} … {/capture} |
captures a section to a variable |
{varType} |
declares type of variable |
{varPrint} |
suggests types of variables |
{templateType} |
declares types of variables using class |
{templatePrint} |
generates class with properties |
{_string} |
prints translated |
{translate} … {/translate} |
translates the content |
{contentType} |
switches the escaping mode and sends HTTP header |
{debugbreak} |
sets breakpoint to the code |
{do} |
evaluates an expression without printing it |
{dump} |
dumps variables to the Tracy Bar |
{php} |
executes any PHP code |
{spaceless} … {/spaceless} |
removes unnecessary whitespace |
{syntax} |
switches the syntax at runtime |
{trace} |
shows stack trace |
n:class |
smart class attribute |
n:attr |
smart HTML attributes |
n:tag |
dynamic name of HTML element |
n:ifcontent |
omit empty HTML tag |
n:href |
link in <a> HTML
elements |
{link} |
prints a link |
{plink} |
prints a link to a presenter |
{control} |
prints a component |
{snippet} … {/snippet} |
a template snippet that can be sent by AJAX |
{snippetArea} |
snippets envelope |
{cache} … {/cache} |
caches a template section |
{form} … {/form} |
prints a form element |
{label} … {/label} |
prints a form input label |
{input} |
prints a form input element |
{inputError} |
prints error message for form input element |
n:name |
activates an HTML input element |
{formContainer} … {/formContainer} |
rendering the form container |
Printing
{$var}
{...}
{=...}
Latte uses the {=...}
tag to print any expression to the output. If the expression starts with a variable or
function call, there is no need to write an equal sign. Which in practice means that it almost never needs to be written:
Name: {$name} {$surname}<br>
Age: {date('Y') - $birth}<br>
You can write anything you know from PHP as an expression. You just don't have to learn a new language. For example:
{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION}
Please don't look for any meaning in the previous example, but if you find one there, write to us :-)
Escaping Output
What is the most important task of a template system? To avoid security holes. And that's exactly what Latte does whenever you print something to output. It automatically escapes everything:
<p>{='one < two'}</p> {* prints: '<p>one < two</p>' *}
To be precise, Latte uses context-sensitive escaping, which is such an important and unique feature that we've devoted a separate chapter to it.
And if you print HTML-encoded content from a trusted source? Then you can easily turn off escaping:
{$trustedHtmlString|noescape}
Misuse of the noescape
filter can lead to an XSS vulnerability! Never use it unless you are
absolutely sure what you are doing and that the string you are printing comes from a trusted source.
Printing in JavaScript
Thanks to context-sensitive escaping, it is wonderfully easy to print variables inside JavaScript, and Latte will properly escape them.
The variable does not have to be a string, any data type is supported, which is then encoded as JSON:
{var $foo = ['hello', true, 1]}
<script>
alert({$foo});
</script>
Generates:
<script>
alert(["hello", true, 1]);
</script>
This is also the reason why do not put variable in quotes: Latte adds them around strings. And if you want to put a string variable into another string, simply concatenate them:
<script>
alert('Hello ' + {$name} + '!'); // OK
alert({="Hello $name!"}); // OK
alert('Hello {$name} !'); // ERROR!
</script>
Filters
The printed expression can be modified by filters. For example, this example converts the string to uppercase and shorten it to a maximum of 30 characters:
{$string|upper|truncate:30}
You can also apply filters to parts of an expression as follows:
{$left . ($middle|upper) . $right}
Conditions
{if}
{elseif}
{else}
Conditions behave the same way as their PHP counterparts. You can use the same expressions as you know from PHP, you don't have to learn a new language.
{if $product->inStock > Stock::Minimum}
In stock
{elseif $product->isOnWay()}
On the way
{else}
Not available
{/if}
Like any pair tag, a pair of {if} ... {/ if}
can be written as n:attribute, for example:
<p n:if="$count > 0">In stock {$count} items</p>
Do you know that you can add prefix tag-
to n:attributes? Then the condition will affects only the HTML tags and
the content between them will always be printed:
<a href="..." n:tag-if="$clickable">Hello</a>
{* prints 'Hello' when $clickable is falsey *}
{* prints '<a href="...">Hello</a>' when $clickable is truthy *}
Nice.
n:else
If you write the {if} ... {/if}
condition in the form of an n:attribute,
you have the option to specify an alternative branch using n:else
:
<strong n:if="$count > 0">In stock {$count} items</strong>
<em n:else>not available</em>
The n:else
attribute can also be used in conjunction with n:ifset
,
n:foreach
, n:try
, n:ifcontent
, and n:ifchanged
.
{/if $cond}
You may be surprised that the expression in the {if}
condition can also be specified in the end tag. This is
useful in situations where we do not yet know the value of the condition when tag is opened. Let's call it a deferred
decision.
For example, we start listing a table with records from the database, and only after completing the report do we realize that
there was no record in the database. So we put condition in the end tag {/if}
and if there is no record, none of it
will be printed:
{if}
<h1>Printing rows from the database</h1>
<table>
{foreach $resultSet as $row}
...
{/foreach}
</table>
{/if isset($row)}
Handy, isn't it?
You can also use {else}
in the deferred condition, but not {elseif}
.
{ifset}
{elseifset}
See also {ifset block}
Use the {ifset $var}
condition to determine if a variable (or multiple variables) exists and has a non-null value.
It's actually the same as if (isset($var))
in PHP. Like any pair tag, this can be written in the form of n:attribute, so let's show it in example:
<meta name="robots" content={$robots} n:ifset="$robots">
{ifchanged}
{ifchanged}
checks if the value of a variable has changed since the last iteration in the loop (foreach, for, or
while).
If we specify one or more variables in the tag, it will check if any of them have changed and prints the contents accordingly. For example, the following example prints the first letter of a name as a heading each time it changes when listing names:
{foreach ($names|sort) as $name}
{ifchanged $name[0]} <h2>{$name[0]}</h2> {/ifchanged}
<p>{$name}</p>
{/foreach}
However, if no argument is given, the rendered content itself will be checked against its previous state. This means that in the previous example, we can safely omit the argument in the tag. And of course we can also use n:attribute:
{foreach ($names|sort) as $name}
<h2 n:ifchanged>{$name[0]}</h2>
<p>{$name}</p>
{/foreach}
You can also include a {else}
clause inside the {ifchanged}
.
{switch}
{case}
{default}
Compares value with multiple options. This is similar to the switch
structure you know from PHP. However, Latte
improves it:
- uses strict comparison (
===
) - does not need a
break
So it is the exact equivalent of the match
structure that PHP 8.0 comes with.
{switch $transport}
{case train}
By train
{case plane}
By plane
{default}
Differently
{/switch}
Clause {case}
can contain multiple values separated by commas:
{switch $status}
{case $status::New}<b>new item</b>
{case $status::Sold, $status::Unknown}<i>not available</i>
{/switch}
Loops
In Latte, all the loops you know from PHP are available to you: foreach, for and while.
{foreach}
You write the cycle exactly the same way as in PHP:
{foreach $langs as $code => $lang}
<span>{$lang}</span>
{/foreach}
In addition, he has some handy tweaks that we will talk about now.
For example, Latte checks that created variables do not accidentally overwrite global variables of the same name. This will
save you when you assume that $lang
is the current language of the page, and you don't realize that
foreach $langs as $lang
has overwritten that variable.
The foreach loop can also be written very elegantly and economically with n:attribute:
<ul>
<li n:foreach="$items as $item">{$item->name}</li>
</ul>
Did you know that you can prepend the inner-
prefix to n:attributes? Now then only the inside part of the element
will be repeated in the loop:
<div n:inner-foreach="$items as $item">
<h4>{$item->title}</h4>
<p>{$item->description}</p>
</div>
So it prints something like:
<div>
<h4>Foo</h4>
<p>Lorem ipsum.</p>
<h4>Bar</h4>
<p>Sit dolor.</p>
</div>
{else}
The foreach
loop can take an optional {else}
clause whose text is displayed if the given array
is empty:
<ul>
{foreach $people as $person}
<li>{$person->name}</li>
{else}
<li><em>Sorry, no users in this list</em></li>
{/foreach}
</ul>
$iterator
Inside the foreach
loop the $iterator
variable is initialized. It holds important information about
the current loop.
$iterator->first
– is this the first iteration?$iterator->last
– is this the last iteration?$iterator->counter
– iteration counter, starts from 1$iterator->counter0
– iteration counter, starts from 0$iterator->odd
– is this iteration odd?$iterator->even
– is this iteration even?$iterator->parent
– the iterator surrounding the current one$iterator->nextValue
– the next item in the loop$iterator->nextKey
– the key of next item in the loop
{foreach $rows as $row}
{if $iterator->first}<table>{/if}
<tr id="row-{$iterator->counter}">
<td>{$row->name}</td>
<td>{$row->email}</td>
</tr>
{if $iterator->last}</table>{/if}
{/foreach}
The latte is smart and $iterator->last
works not only for arrays, but also when the loop runs over a general
iterator where the number of items is not known in advance.
{first}
{last}
{sep}
These tags can be used inside the {foreach}
loop. The contents of {first}
are rendered for the first
pass. The contents of {last}
are rendered … can you guess? Yes, for the last pass. These are actually shortcuts for
{if $iterator->first}
and {if $iterator->last}
.
The tags can also be written as n:attributes:
{foreach $rows as $row}
{first}<h1>List of names</h1>{/first}
<p>{$row->name}</p>
<hr n:last>
{/foreach}
The contents of the {sep}
are rendered if the iteration is not the last, so it is suitable for printing
delimiters, such as commas between listed items:
{foreach $items as $item} {$item} {sep}, {/sep} {/foreach}
That's pretty practical, isn't it?
{iterateWhile}
Simplifies the grouping of linear data during iteration in a foreach loop by iterating in a nested loop until a condition is satisfied. Read the detailed instructions.
It can also elegantly replace {first}
and {last}
in the example above:
{foreach $rows as $row}
<table>
{iterateWhile}
<tr id="row-{$iterator->counter}">
<td>{$row->name}</td>
<td>{$row->email}</td>
</tr>
{/iterateWhile true}
</table>
{/foreach}
See also batch and group filters.
{for}
We write the cycle in exactly the same way as in PHP:
{for $i = 0; $i < 10; $i++}
<span>Item #{$i}</span>
{/for}
The tag can also be written as n:attribute:
<h1 n:for="$i = 0; $i < 10; $i++">{$i}</h1>
{while}
Again, we write the cycle in exactly the same way as in PHP:
{while $row = $result->fetch()}
<span>{$row->title}</span>
{/while}
Or as n:attribute:
<span n:while="$row = $result->fetch()">
{$row->title}
</span>
A variant with a condition in the end tag corresponds to the do-while loop in PHP:
{while}
<span>{$item->title}</span>
{/while $item = $item->getNext()}
{continueIf}
{skipIf}
{breakIf}
There are special tags you can use to control any loop – {continueIf ?}
and {breakIf ?}
which jump
to the next iteration and end the loop, respectively, if the conditions are met:
{foreach $rows as $row}
{continueIf $row->date < $now}
{breakIf $row->parent === null}
...
{/foreach}
Tag {skipIf}
is very similar to {continueIf}
, but does not increment the counter. So there are no
holes in the numbering when you print $iterator->counter
and skip some items. Also the {else} clause will be
rendered when you skip all items.
<ul>
{foreach $people as $person}
{skipIf $person->age < 18}
<li>{$iterator->counter}. {$person->name}</li>
{else}
<li><em>Sorry, no adult users in this list</em></li>
{/foreach}
</ul>
{exitIf}
Ends the rendering of a template or block when a condition is met (i.e. „early exit“).
{exitIf !$messages}
<h1>Messages</h1>
<div n:foreach="$messages as $message">
{$message}
</div>
Including Templates
{include 'file.latte'}
See also {include block}
The {include}
tag loads and renders the specified template. In our favorite PHP language it's like:
<?php include 'header.phtml'; ?>
Included templates have not access to the variables of the active context, but have access to the global variables.
You can pass variables to the inserted template in the following way:
{include 'template.latte', foo: 'bar', id: 123}
The template name can be any PHP expression:
{include $someVar}
{include $ajax ? 'ajax.latte' : 'not-ajax.latte'}
The inserted content can be modified using filters. The following example removes all HTML stuff and adjusts the case:
<title>{include 'heading.latte' |stripHtml|capitalize}</title>
The template inheritance is not involved in this by default. While you can add
block tags to templates that are included, they will not replace matching blocks in the template they are included into. Think of
includes as independent and shielded parts of pages or modules. This behavior can be changed using the modifier
with blocks
:
{include 'template.latte' with blocks}
The relationship between the file name specified in the tag and the file on disk is a matter of loader.
{sandbox}
When including a template created by an end user, you should consider sandboxing it (more information in the sandbox documentation):
{sandbox 'untrusted.latte', level: 3, data: $menu}
{block}
See also {block name}
Blocks without a name serve to the ability to apply filters to a part of template. For example, you can apply a strip filter to remove unnecessary spaces:
{block|strip}
<ul>
<li>Hello World</li>
</ul>
{/block}
Exception Handling
{try}
This tags makes it extremely easy to build robust templates.
If an exception occurs while rendering the {try}
block, the entire block is thrown away and rendering will
continue after it:
{try}
<ul>
{foreach $twitter->loadTweets() as $tweet}
<li>{$tweet->text}</li>
{/foreach}
</ul>
{/try}
The contents of the optional clause {else}
are rendered only when an exception occurs:
{try}
<ul>
{foreach $twitter->loadTweets() as $tweet}
<li>{$tweet->text}</li>
{/foreach}
</ul>
{else}
<p>Sorry, the tweets could not be loaded.</p>
{/try}
The tag can also be written as n:attribute:
<ul n:try>
...
</ul>
It is also possible to define own exception handler for i.e logging:
{rollback}
The {try}
block can also be stopped and skipped manually using {rollback}
. So you do not have to
check all the input data in advance, and only during rendering you can decide whether it makes sense to render the object.
{try}
<ul>
{foreach $people as $person}
{skipIf $person->age < 18}
<li>{$person->name}</li>
{else}
{rollback}
{/foreach}
</ul>
{/try}
Variables
{var}
{default}
We will create new variables in the template with the {var}
tag:
{var $name = 'John Smith'}
{var $age = 27}
{* Multiple declaration *}
{var $name = 'John Smith', $age = 27}
The {default}
tag works similarly, except that it creates variables only if they do not exist. If a variable
already exists and contains null
, it will not be overwritten:
{default $lang = 'cs'}
You can also specify types of variables. For now, they are informative and Latte does not check them.
{var string $name = $article->getTitle()}
{default int $id = 0}
{parameters}
Just as a function declares its parameters, a template can declare its variables at its beginning:
{parameters
$a,
?int $b,
int|string $c = 10
}
Variables $a
and $b
without a default value automatically have a default value of null
.
The declared types are still informative and Latte does not check them.
Other than the declared variables are not passed into the template. This is a difference from the
{default}
tag.
{capture}
By using {capture}
tag you can capture the output to a variable:
{capture $var}
<ul>
<li>Hello World</li>
</ul>
{/capture}
<p>Captured: {$var}</p>
The tag can also be written as n:attribute, like any pairwise tag:
<ul n:capture="$var">
<li>Hello World</li>
</ul>
The HTML output is stored in the $var
variable as a Latte\Runtime\Html
object to avoid unwanted escaping when printing.
Others
{contentType}
Use the tag to specify what type of content the template represents. The options are:
html
(default type)xml
javascript
css
calendar
(iCal)text
Its use is important because it sets context-sensitive escaping and
only then can Latte escape correctly. For example, {contentType xml}
switches to XML mode,
{contentType text}
turns off escaping completely.
If the parameter is a full-featured MIME type, such as application/xml
, it also sends an HTTP header
Content-Type
to the browser:
{contentType application/xml}
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>RSS feed</title>
<item>
...
</item>
</channel>
</rss>
{debugbreak}
Specifies the place where code execution will break. It is used for debugging purposes for the programmer to inspect the runtime environment and to ensure the code runs as expected. It supports Xdebug. Additionally, you can specify a condition when the code should break.
{debugbreak} {* breaks the program *}
{debugbreak $counter == 1} {* breaks the program if the condition is met *}
{do}
Executes the PHP code and doesn't print anything. As with all other tags, PHP code is a single expression, see PHP limitations.
{do $num++}
{dump}
Dumps a variable or current context.
{dump $name} {* dumps the $name variable *}
{dump} {* dumps all the defined variables *}
Requires package Tracy.
{php}
Allows you to execute any PHP code. The tag must be activated using the RawPhpExtension extension.
{spaceless}
Removes unnecessary whitespace. It is similar to spaceless filter.
{spaceless}
<ul>
<li>Hello</li>
</ul>
{/spaceless}
Outputs:
<ul> <li>Hello</li> </ul>
The tag can also be written as n:attribute:
{syntax}
Latte tags do not have to be enclosed in single curly braces only. You can choose another separator, even at runtime. This is
done by {syntax…}
, where the parameter can be:
- double:
{{...}}
- off: completely disables Latte tags
By using the n:attribute notation we can disable Latte for a JavaScript block only:
<script n:syntax="off">
var obj = {var: 123}; // this isn't a tag any more
</script>
Latte can be used very comfortably inside JavaScript, just avoid constructs like in this example, where the letter immediately
follows {
, see Latte inside JavaScript or CSS.
If you turn off Latte with the {syntax off}
(ie tag, not the n:attribute), it will strictly ignore all tags up to
{/syntax}
.
{trace}
Throws an Latte\RuntimeException
exception, whose stack trace is in the spirit of the templates. Thus, instead of
calling functions and methods, it involves calling blocks and inserting templates. If you use a tool for clearly displaying thrown
exceptions, such as Tracy, you will clearly see the call stack, including all passed
arguments.
HTML Tag Helpers
n:class
Thanks to n:class
, it is very easy to generate the HTML attribute class
exactly as you need.
Example: I need the active element to have the active
class:
{foreach $items as $item}
<a n:class="$item->isActive() ? active">...</a>
{/foreach}
And I further need that the first element have the classes first
and main
:
{foreach $items as $item}
<a n:class="$item->isActive() ? active, $iterator->first ? 'first main'">...</a>
{/foreach}
And all elements should have the list-item
class:
{foreach $items as $item}
<a n:class="$item->isActive() ? active, $iterator->first ? 'first main', list-item">...</a>
{/foreach}
Amazingly simple, isn't it?
n:attr
The n:attr
attribute can generate arbitrary HTML attributes with the same elegance as n:class.
{foreach $data as $item}
<input type="checkbox" n:attr="value: $item->getValue(), checked: $item->isActive()">
{/foreach}
Depending on the returned values, it displays eg:
<input type="checkbox">
<input type="checkbox" value="Hello">
<input type="checkbox" value="Hello" checked>
n:tag
The n:tag
attribute can dynamically change the name of an HTML element.
<h1 n:tag="$heading" class="main">{$title}</h1>
If $heading === null
, the <h1>
tag is printed without change. Otherwise, the element name is
changed to the value of the variable, so for $heading === 'h3'
it writes:
<h3 class="main">...</h3>
Because Latte is a secure templating system, it checks that the new tag name is valid and does not contain any unwanted or malicious values.
n:ifcontent
Prevents an empty HTML element from being printed, ie an element containing nothing but whitespace.
<div>
<div class="error" n:ifcontent>{$error}</div>
</div>
Depending on the values of the variable $error
this will print:
{* $error = '' *}
<div>
</div>
{* $error = 'Required' *}
<div>
<div class="error">Required</div>
</div>
Translation
To make the translation tags work, you need to set up translator. You can
also use the translate
filter for translation.
{_...}
Translates values into other languages.
<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
Other parameters can also be passed to the translator:
<a href="basket">{_'Basket', domain: order}</a>
{translate}
Překládá části šablony:
<h1>{translate}Order{/translate}</h1>
{translate domain: order}Lorem ipsum ...{/translate}
The tag can also be written as n:attribute, to translate the inside of the element:
<h1 n:translate>Order</h1>