Syntax

Latte syntax wasn't invented by engineers but came up from web designer's practical requests. We were looking for the friendliest syntax with which you can write even the most problematic constructions comfortably enough. You will be surprised how much help Latte can be.

You can find tags for advanced layout managing, for template inheritance, nested blocks and so on. Syntax comes from PHP itself so you don't have to learn anything new and you can leverage your know-how.

Tags

You can find detailed description of all the built-in tags. Furthermore, you can make your own tags.

Each pair tag, such as {if} … {/if}, operating upon single HTML element can be written in n:attribute notation. So, it is possible to write the {foreach} tag in the same manner:

<ul n:if="$items">
	<li n:foreach="$items as $item">{$item|capitalize}</li>
</ul>

With n:attributes you can do much more interesting tricks as you will see in a moment.

{$item|capitalize} tag which prints the $item variable contains so called filter, in this case the capitalize filter which makes the first letter of each word uppercase.

A very important feature of Latte is that it escapes variables by default. Escaping is needed when printing a variable because we have to convert all the characters which have a special meaning in HTML to other sequences. In case we forget it can lead to a serious security hole called Cross-Site Scripting (XSS).

Because of different escaping functions that are needed in different documents and different parts of a page, Latte features a unique technology of security which recognizes the context in which the tag is placed and chooses the right escaping mode. You don't have to worry that your coder forgets about it causing you goosebumps because of a security hole. Which is great!

If the $item variable stores an HTML code and you want to print it without any alteration you just add the modifier noescape: {$item|noescape}. Forgetting the modifier mark won't cause any security holes in the spirit of „less code, more security“ principle.

You can still use PHP inside the tags normally, including comments as well. But Latte also extends the PHP syntax with three pleasant features:

  1. we can omit quotes around the strings consisting of letters, numbers, and dashes
  2. short condition notation $a ? 'b' which is the same as $a ? 'b' : null in PHP
  3. you can use optional chaining like $var?->call()?->elem[1]?->item

For example:

{$cond ? hello}  // prints 'hello' if $cond equals true

{$order->item?->name} // means isset($order->item) ? $order->item->name : null

n:attributes

We showed that n:attributes are supposed to be written directly into HTML tags as their special attributes. We also said that every pair tag (e.g. {if} … {/if}) can be written in n:attribute notation. The functionality then corresponds to the HTML element in which it is written:

{var $items = ['I', '♥', 'Nette Framework']}

<p n:foreach="$items as $item">{$item}</p>

Prints:

<p>I</p>
<p>♥</p>
<p>Nette Framework</p>

By using inner- prefix we can alter the behavior so that the functionality applies only to the body of the element:

<div n:inner-foreach="$items as $item">
	<p>{$item}</p>
	<hr>
</div>

Prints:

<div>
	<p>I</p>
	<hr>
	<p>♥</p>
	<hr>
	<p>Nette Framework</p>
	<hr>
</div>

Or by using tag- prefix the functionality is applied on the HTML tags only:

<p><a href="{$url}" n:tag-if="$url">Title</a></p>

Depending on the value of $url variable this will print:

// when $url is empty
<p>Title</p>

// when $url equals 'https://nette.org'
<p><a href="https://nette.org">Title</a></p>

However, n:attributes are not only a shortcut for pair tags, there are some pure n:attributes as well, for example the coder's best friend n:class.

Filters

See the summary of standard filters.

Latte allows calling filters by using the pipe sign notation (preceding space is allowed):

<h1>{$heading|upper}</h1>

Filters can be chained, in that case they apply in order from left to right:

<h1>{$heading|lower|capitalize}</h1>

Parameters are put after the filter name separated by colon or comma:

<h1>{$heading|truncate:20,''}</h1>

Filters can be applied on expression:

{var $name = ($title|upper) . ($subtitle|lower)}</h1>

On block:

<h1>{block |lower}{$heading}{/block}</h1>

Or directly on value (in combination with {=expr} tag):

<h1>{='  Hello world  '|trim}<h1>

Expressions

Optional Chaining with Nullsafe Operator

Optional chaining lets us write code where Latte immediately stops evaluating expressions if it encounters null. With the new ?-> operator allowing optional access to variables or array elements. PHP 8 brings the same thing, but you can also use it in PHP 7 in Latte.

When we write code like

{$order?->id}

this is a way of saying that when $order is not null, $order->id will be computed, but when $order is null, stop what we’re doing and just return null.

You might find yourself using ?-> to replace a lot of code that performs repetitive nullish checks:

{$user?->address?->street}
// roughly means ($user !== null) && ($user->address !== null) ? $user->address->street : null

{$items[2]?->count}
// roughly means ($items[2] !== null) ? $items[2]->count : null

{$user->getIdentity()?->name}
// roughly means $user->getIdentity() !== null ? $user->getIdentity()->name : null

The meaning are “roughly” because in fact the expression is evaluated more sophistically and no step is repeated. For example, $user->getIdentity() is called only once, so there cannot be a problem due to an object being returned in the condition and then null.

Optional chaining expressions can be used anywhere, for example, in terms of:

{if $blogPost?->count('*')}
	// means if (isset($blogPost) && $blogPost->count('*'))
	...
{/if}

Optional Chaining with Undefined-safe Operator

The undefined-safe operator ??-> is similar to the nullsafe operator ?->, but does not raise an error if a variable, property, or index does not exist at all.

{$order??->id}

this is a way of saying that when $order is defined and not null, $order->id will be computed, but when $order is null or doesn't exist, stop what we’re doing and just return null.

You might find yourself using ?-> to replace a lot of code that performs repetitive nullish checks:

{$user??->address??->street}
// roughly means isset($user) && isset($user->address) ? $user->address->street : null

Array Expansion Operator (expand)

The (expand) operator allows you to use an array where multiple arguments are expected. This is the equivalent of the ... operator from PHP, but retaining the keys.

It can be used, for example, to pass arguments into blocks or included templates if we have them in the array.

{include 'foobar.latte' (expand) $args}          {* arguments for include *}

Comments

Latte also has a {* comment tag *} which doesn't get printed to the output.