Nette Documentation Preview

syntax
Теги Latte
**********

.[perex]
Сводка и описание всех встроенных тегов Latte.

.[table-latte-tags language-latte]
|## Печать
| `{$var}`, `{...}` или `{=...}` | [печатает экранированную переменную или выражение |#Printing]
| `{$var\|filter}` | [печатает с фильтрами |#Filters]
| `{l}` или `{r}` | печатает символ `{` or `}`

.[table-latte-tags language-latte]
|## Условия
| `{if}`... `{elseif}`... `{else}`... `{/if}` | [условие if |#if-elseif-else]
| `{ifset}`... `{elseifset}`... `{/ifset}` | [условие ifset |#ifset-elseifset]
| `{ifchanged}`... `{/ifchanged}` | [проверка наличия изменений |#ifchanged]
| `{switch}` `{case}` `{default}` `{/switch}` | [условие switch |#switch-case-default]
| `n:else` | [альтернативное содержание условий |#n:else]

.[table-latte-tags language-latte]
|## Loops
| `{foreach}`... `{/foreach}` | [foreach |#foreach]
| `{for}`... `{/for}` | [for |#for]
| `{while}`... `{/while}` | [while |#while]
| `{continueIf $cond}` | [перейти к следующей итерации |#continueIf-skipIf-breakIf]
| `{skipIf $cond}` | [пропустить текущую итерацию цикла |#continueIf-skipIf-breakIf]
| `{breakIf $cond}` | [прервать цикл |#continueIf-skipIf-breakIf]
| `{exitIf $cond}` | [ранний выход |#exitIf]
| `{first}`... `{/first}` | [это первая итерация? |#first-last-sep]
| `{last}`... `{/last}` | [Это последняя итерация? |#first-last-sep]
| `{sep}`... `{/sep}` | [последует ли следующая итерация? |#first-last-sep]
| `{iterateWhile}`... `{/iterateWhile}` | [структурированный foreach |#iterateWhile]
| `$iterator` | [специальная переменная внутри цикла foreach |#iterator]

.[table-latte-tags language-latte]
|## Включение других шаблонов
| `{include 'file.latte'}` | [включает шаблон из другого файла |#include]
| `{sandbox 'file.latte'}` | [включает шаблон в режиме песочницы |#sandbox]

.[table-latte-tags language-latte]
|## Блоки, макеты, наследование шаблонов
| `{block}` | [анонимный блок |#block]
| `{block blockname}` | [определение блока |template-inheritance#Blocks]
| `{define blockname}` | [определение блока для будущего использования |template-inheritance#Definitions]
| `{include blockname}` | [печатает блок |template-inheritance#Printing-Blocks]
| `{include blockname from 'file.latte'}` | [печатает блок из файла |template-inheritance#Printing-Blocks]
| `{import 'file.latte'}` | [загружает блоки из другого шаблона |template-inheritance#Horizontal-Reuse]
| `{layout 'file.latte'}` / `{extends}` | [указание файла макета |template-inheritance#Layout-Inheritance]
| `{embed}`... `{/embed}` | [загружает шаблон или блок и позволяет перезаписывать блоки |template-inheritance#Unit-Inheritance]
| `{ifset blockname}`... `{/ifset}` | [условие, если блок определен |template-inheritance#Checking-Block-Existence]

.[table-latte-tags language-latte]
|## Обработка исключений
| `{try}`... `{else}`... `{/try}` | [перехват исключений |#try]
| `{rollback}` | [отбрасывает блок try |#rollback]

.[table-latte-tags language-latte]
|## Переменные
| `{var $foo = value}` | [создание переменных |#var-default]
| `{default $foo = value}` | [значение по умолчанию, когда переменная не объявлена |#var-default]
| `{parameters}` | [Объявление переменных, типы значений по умолчанию |#parameters]
| `{capture}`... `{/capture}` | [Захватывает секцию для переменной |#capture]

.[table-latte-tags language-latte]
|## Типы
| `{varType}` | [объявляет тип переменной |type-system#varType]
| `{varPrint}` | [предлагает типы переменных |type-system#varPrint]
| `{templateType}` | [объявляет типы переменных с помощью класса |type-system#templateType]
| `{templatePrint}` | [генерирует класс со свойствами |type-system#templatePrint]

.[table-latte-tags language-latte]
|## Перевод
| `{_string}` | [печатает перевод |#Translation]
| `{translate}`... `{/translate}` | [переводит содержимое |#Translation]

.[table-latte-tags language-latte]
|## Другие
| `{contentType}` | [переключает режим экранирования и отправляет HTTP-заголовок |#contentType]
| `{debugbreak}` | [устанавливает точку останова в коде |#debugbreak]
| `{do}` | [оценивает выражение, не выводя его на печать |#do]
| `{dump}` | [сбрасывает переменные в Tracy Bar |#dump]
| `{php}` | [выполняет любой PHP-код |#php]
| `{spaceless}`... `{/spaceless}` | [удаляет ненужные пробельные символы |#spaceless]
| `{syntax}` | [переключает синтаксис во время выполнения программы|#Syntax]
| `{trace}` | [показывает трассировку стека |#trace]

.[table-latte-tags language-latte]
|## Помощники HTML тегов
| `n:class` | [умный атрибут класса |#n-class]
| `n:attr` | [интеллектуальные атрибуты HTML |#n-attr]
| `n:tag` | [динамическое имя элемента HTML |#n-tag]
| `n:ifcontent` | [Опустить пустой HTML-тег |#n-ifcontent]

.[table-latte-tags language-latte]
|## Доступно только в Nette Framework
| `n:href` | [ссылка в HTML-элементах `<a>`  |application:creating-links#In-the-Presenter-Template]
| `{link}` | [печатает ссылку |application:creating-links#In-the-Presenter-Template]
| `{plink}` | [печатает ссылку на ведущего |application:creating-links#In-the-Presenter-Template]
| `{control}` | [печатает компонент |application:components#Rendering]
| `{snippet}`... `{/snippet}` | [фрагмент шаблона, который может быть отправлен с помощью AJAX |application:ajax#snippets-in-latte]
| `{snippetArea}` | [конверт сниппетов |application:ajax#snippet-areas]
| `{cache}`... `{/cache}` | [кэширует раздел шаблона |caching:#Caching-in-Latte]

.[table-latte-tags language-latte]
|## Доступно только в Nette Forms
| `{form}`... `{/form}` | [печатает элемент формы |forms:rendering#form]
| `{label}`... `{/label}` | [печатает метку ввода формы |forms:rendering#label-input]
| `{input}` | [печатает элемент ввода формы |forms:rendering#label-input]
| `{inputError}` | [печатает сообщение об ошибке для элемента ввода формы |forms:rendering#inputError]
| `n:name` | [активирует элемент ввода HTML |forms:rendering#n:name]
| `{formContainer}`... `{/formContainer}` | [рендеринг контейнера формы |forms:rendering#special-cases]


Печать .[#toc-printing]
=======================


`{$var}` `{...}` `{=...}`
-------------------------

Latte использует тег `{=...}` для печати любого выражения на выходе. Если выражение начинается с переменной или вызова функции, то нет необходимости писать знак равенства. Что на практике означает, что его почти никогда не нужно писать:

```latte
Name: {$name} {$surname}<br>
Age: {date('Y') - $birth}<br>
```

Вы можете записать в виде выражения все, что знаете из PHP. Вам просто не нужно учить новый язык. Например:


```latte
{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION}
```

Пожалуйста, не ищите никакого смысла в предыдущем примере, но если вы его там найдете, напишите нам :-)


Эскейпинг-вывод .[#toc-escaping-output]
---------------------------------------

Какая самая важная задача системы шаблонов? Избегать дыр в безопасности. И именно это делает Latte, когда вы печатаете что-то на вывод. Он автоматически экранирует все:

```latte
<p>{='one < two'}</p>   {* prints: '<p>one &lt; two</p>' *}
```

Если быть точным, Latte использует контекстно-зависимую экранировку, которая является настолько важной и уникальной особенностью, что мы посвятили ей [отдельную главу|safety-first#context-aware-escaping].

А если вы печатаете HTML-кодированное содержимое из надежного источника? Тогда вы можете легко отключить экранирование:

```latte
{$trustedHtmlString|noescape}
```

.[warning]
Неправильное использование фильтра `noescape` может привести к XSS-уязвимости! Никогда не используйте его, если вы не **абсолютно уверены** в том, что вы делаете, и что печатаемая вами строка получена из надежного источника.


Печать в JavaScript .[#toc-printing-in-javascript]
--------------------------------------------------

Благодаря контекстно-зависимому экранированию, очень легко печатать переменные в JavaScript, и Latte будет правильно их экранировать.

Переменная не обязательно должна быть строкой, поддерживается любой тип данных, которые затем кодируются как JSON:

```latte
{var $foo = ['hello', true, 1]}
<script>
	alert({$foo});
</script>
```

Генерирует:

```latte
<script>
	alert(["hello", true, 1]);
</script>
```

Это также причина, по которой **не заключайте переменную в кавычки**: Latte добавляет их вокруг строк. А если вы хотите поместить строковую переменную в другую строку, просто конкатенируйте их:

```latte
<script>
	alert('Hello ' + {$name} + '!');  // OK

	alert({="Hello $name!"});         // OK

	alert('Hello {$name} !');         // ERROR!
</script>
```


Фильтры .[#toc-filters]
-----------------------

Печатное выражение может быть изменено с [помощью фильтров |syntax#Filters]. Например, в этом примере строка преобразуется в верхний регистр и сокращается максимум до 30 символов:

```latte
{$string|upper|truncate:30}
```

Вы также можете применять фильтры к частям выражения следующим образом:

```latte
{$left . ($middle|upper) . $right}
```


Условия .[#toc-conditions]
==========================


`{if}` `{elseif}` `{else}`
--------------------------

Условия ведут себя так же, как и их аналоги в PHP. Вы можете использовать те же выражения, которые вы знаете из PHP, вам не нужно изучать новый язык.

```latte
{if $product->inStock > Stock::Minimum}
	In stock
{elseif $product->isOnWay()}
	On the way
{else}
	Not available
{/if}
```

Как и любой парный тег, пара `{if} ... {/ if}` может быть записана как [n:attribute |syntax#n-attributes], например:

```latte
<p n:if="$count > 0">In stock {$count} items</p>
```

Знаете ли вы, что к n:attributes можно добавить префикс `tag-`? Тогда условие будет затрагивать только HTML-теги, а содержимое между ними всегда будет выводиться:

```latte
<a href="..." n:tag-if="$clickable">Hello</a>

{* prints 'Hello' when $clickable is falsey *}
{* prints '<a href="...">Hello</a>' when $clickable is truthy *}
```

Отлично.


`n:else` .{data-version:3.0.11}
-------------------------------

Если условие `{if} ... {/if}` записано в виде [атрибута n:attribute |syntax#n:attributes], то у вас есть возможность указать альтернативную ветвь с помощью `n:else`:

```latte
<strong n:if="$count > 0">In stock {$count} items</strong>

<em n:else>not available</em>
```

Атрибут `n:else` также может использоваться в сочетании с. [`n:ifset` |#ifset-elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [`n:ifcontent` |#n:ifcontent], и [`n:ifchanged` |#ifchanged].


`{/if $cond}`
-------------

Вас может удивить, что выражение в условии `{if}` также может быть указано в теге end. Это полезно в ситуациях, когда мы еще не знаем значение условия на момент открытия тега. Назовем это отложенным решением.

Например, мы начинаем выводить таблицу с записями из базы данных, и только после завершения отчета понимаем, что в базе данных не было ни одной записи. Поэтому мы помещаем условие в конечный тег `{/if}`, и если записи нет, то ничего из этого не будет напечатано:

```latte
{if}
	<h1>Printing rows from the database</h1>

	<table>
	{foreach $resultSet as $row}
		...
	{/foreach}
	</table>
{/if isset($row)}
```

Удобно, не правда ли?

Вы также можете использовать `{else}` в отложенном условии, но не `{elseif}`.


`{ifset}` `{elseifset}`
-----------------------

.[note]
См. также [`{ifset block}` |template-inheritance#Checking-Block-Existence]

Используйте условие `{ifset $var}`, чтобы определить, существует ли переменная (или несколько переменных) и имеет ли она ненулевое значение. На самом деле это то же самое, что и `if (isset($var))` в PHP. Как и любой парный тег, этот может быть записан в виде [n:attribute |syntax#n-attributes], поэтому покажем его на примере:

```latte
<meta name="robots" content={$robots} n:ifset="$robots">
```


`{ifchanged}`
-------------

`{ifchanged}` проверяет, изменилось ли значение переменной с момента последней итерации в цикле (foreach, for или while).

Если мы укажем в теге одну или несколько переменных, он проверит, изменилось ли значение любой из них, и напечатает содержимое соответствующим образом. Например, в следующем примере при перечислении имен в качестве заголовка печатается первая буква имени каждый раз, когда она меняется:

```latte
{foreach ($names|sort) as $name}
	{ifchanged $name[0]} <h2>{$name[0]}</h2> {/ifchanged}

	<p>{$name}</p>
{/foreach}
```

Однако, если аргумент не указан, то будет проверено само содержимое рендеринга в соответствии с его предыдущим состоянием. Это означает, что в предыдущем примере мы можем смело опустить аргумент в теге. И, конечно, мы также можем использовать [n:attribute |syntax#n-attributes]:

```latte
{foreach ($names|sort) as $name}
	<h2 n:ifchanged>{$name[0]}</h2>

	<p>{$name}</p>
{/foreach}
```

Вы также можете включить клаузулу `{else}` внутрь `{ifchanged}`.


`{switch}` `{case}` `{default}`
-------------------------------
Сравнивает значение с несколькими вариантами. Это похоже на структуру `switch`, известную вам из PHP. Однако Latte улучшает ее:

- использует строгое сравнение (`===`)
- не требует `break`

Таким образом, это точный эквивалент структуры `match`, с которой поставляется PHP 8.0.

```latte
{switch $transport}
	{case train}
		By train
	{case plane}
		By plane
	{default}
		Differently
{/switch}
```

Пункт `{case}` может содержать несколько значений, разделенных запятыми:

```latte
{switch $status}
{case $status::New}<b>new item</b>
{case $status::Sold, $status::Unknown}<i>not available</i>
{/switch}
```


Циклы .[#toc-loops]
===================

В Latte доступны все циклы, знакомые вам по PHP: foreach, for и while.


`{foreach}`
-----------

Вы пишете цикл точно так же, как и в PHP:

```latte
{foreach $langs as $code => $lang}
	<span>{$lang}</span>
{/foreach}
```

Кроме того, у него есть несколько удобных твиков, о которых мы сейчас поговорим.

Например, Latte проверяет, чтобы созданные переменные случайно не перезаписали одноименные глобальные переменные. Это спасет вас, когда вы предполагаете, что `$lang` - текущий язык страницы, и не понимаете, что `foreach $langs as $lang` перезаписал эту переменную.

Цикл foreach также может быть написан очень элегантно и экономично с помощью [n:attribute |syntax#n-attributes]:

```latte
<ul>
	<li n:foreach="$items as $item">{$item->name}</li>
</ul>
```

Знаете ли вы, что к n:attributes можно добавлять префикс `inner-`? Тогда в цикле будет повторяться только внутренняя часть элемента:

```latte
<div n:inner-foreach="$items as $item">
	<h4>{$item->title}</h4>
	<p>{$item->description}</p>
</div>
```

Таким образом, будет выведено что-то вроде:

```latte
<div>
	<h4>Foo</h4>
	<p>Lorem ipsum.</p>
	<h4>Bar</h4>
	<p>Sit dolor.</p>
</div>
```


`{else}` .{toc: foreach-else}
-----------------------------

Цикл `foreach` может принимать необязательное предложение `{else}`, текст которого выводится, если заданный массив пуст:

```latte
<ul>
	{foreach $people as $person}
		<li>{$person->name}</li>
	{else}
		<li><em>Sorry, no users in this list</em></li>
	{/foreach}
</ul>
```


`$iterator`
-----------

Внутри цикла `foreach` инициализируется переменная `$iterator`. В ней хранится важная информация о текущем цикле.

- `$iterator->first` - это первая итерация?
- `$iterator->last` - это последняя итерация?
- `$iterator->counter` - счетчик итераций, начинается с 1
- `$iterator->counter0` - счетчик итераций, начинается с 0
- `$iterator->odd` - эта итерация нечетная?
- `$iterator->even` - эта итерация четная?
- `$iterator->parent` - итератор, окружающий текущий итератор.
- `$iterator->nextValue` - следующий элемент в цикле
- `$iterator->nextKey` - ключ следующего элемента в цикле


```latte
{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}
```

Лата умница и `$iterator->last` работает не только для массивов, но и когда цикл работает над общим итератором, где количество элементов заранее не известно.


`{first}` `{last}` `{sep}`
--------------------------

Эти теги можно использовать внутри цикла `{foreach}`. Содержимое `{first}` отображается при первом проходе.
Содержимое `{last}` отображается ... можете догадаться? Да, для последнего прохода. На самом деле это ярлыки для `{if $iterator->first}` и `{if $iterator->last}`.

Теги также могут быть записаны как [n:attributes |syntax#n-attributes]:

```latte
{foreach $rows as $row}
	{first}<h1>List of names</h1>{/first}

	<p>{$row->name}</p>

	<hr n:last>
{/foreach}
```

Содержимое `{sep}` выводится, если итерация не последняя, поэтому он подходит для печати разделителей, например, запятых между элементами списка:

```latte
{foreach $items as $item} {$item} {sep}, {/sep} {/foreach}
```

Это довольно практично, не так ли?


`{iterateWhile}`
----------------

Упрощает группировку линейных данных во время итерации в цикле foreach, выполняя итерацию во вложенном цикле до тех пор, пока не будет выполнено условие. [Ознакомьтесь с подробными инструкциями |cookbook/grouping].

Он также может элегантно заменить `{first}` и `{last}` в примере выше:

```latte
{foreach $rows as $row}
	<table>

	{iterateWhile}
	<tr id="row-{$iterator->counter}">
		<td>{$row->name}</td>
		<td>{$row->email}</td>
	</tr>
	{/iterateWhile true}

	</table>
{/foreach}
```

См. также [пакетные |filters#batch] и [групповые |filters#group] фильтры.


`{for}`
-------

Мы пишем цикл точно так же, как и в PHP:

```latte
{for $i = 0; $i < 10; $i++}
	<span>Item #{$i}</span>
{/for}
```

Тег также может быть записан как [n:attribute |syntax#n-attributes]:

```latte
<h1 n:for="$i = 0; $i < 10; $i++">{$i}</h1>
```


`{while}`
---------

Опять же, мы пишем цикл точно так же, как и в PHP:

```latte
{while $row = $result->fetch()}
	<span>{$row->title}</span>
{/while}
```

Или как [n:attribute |syntax#n-attributes]:

```latte
<span n:while="$row = $result->fetch()">
	{$row->title}
</span>
```

Вариант с условием в конце тега соответствует циклу do-while в PHP:

```latte
{while}
	<span>{$item->title}</span>
{/while $item = $item->getNext()}
```


`{continueIf}` `{skipIf}` `{breakIf}`
-------------------------------------

Существуют специальные теги, которые можно использовать для управления любым циклом - `{continueIf ?}` и `{breakIf ?}`, которые переходят к следующей итерации и завершают цикл, соответственно, при выполнении условий:

```latte
{foreach $rows as $row}
	{continueIf $row->date < $now}
	{breakIf $row->parent === null}
	...
{/foreach}
```


Тег `{skipIf}` очень похож на `{continueIf}`, но не увеличивает счетчик. Таким образом, при печати `$iterator->counter` и пропуске некоторых элементов в нумерации не будет дыр. Также предложение {else} будет выведено при пропуске всех элементов.

```latte
<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}` .{data-version:3.0.5}
--------------------------------

Завершает отрисовку шаблона или блока при выполнении условия.

```latte
{exitIf !$messages}

<h1>Messages</h1>
<div n:foreach="$messages as $message">
   {$message}
</div>
```


Включение шаблонов .[#toc-including-templates]
==============================================


`{include 'file.latte'}` .{toc: include}
----------------------------------------

.[note]
См. также [`{include block}` |template-inheritance#Printing-Blocks]

Тег `{include}` загружает и отображает указанный шаблон. На нашем любимом языке PHP это выглядит так:

```php
<?php include 'header.phtml'; ?>
```

Включенные шаблоны не имеют доступа к переменным активного контекста, но имеют доступ к глобальным переменным.

Вы можете передавать переменные вставленному шаблону следующим образом:

```latte
{include 'template.latte', foo: 'bar', id: 123}
```

Имя шаблона может быть любым выражением PHP:

```latte
{include $someVar}
{include $ajax ? 'ajax.latte' : 'not-ajax.latte'}
```

Вставленное содержимое может быть изменено с помощью [фильтров |syntax#Filters]. В следующем примере удаляется весь HTML и корректируется регистр:

```latte
<title>{include 'heading.latte' |stripHtml|capitalize}</title>
```

По умолчанию [наследование шаблона |template inheritance] **не участвует** в этом. Хотя вы можете добавлять теги блоков в включаемые шаблоны, они не будут заменять соответствующие блоки в шаблоне, в который они включены. Рассматривайте включаемые блоки как независимые и экранированные части страниц или модулей. Это поведение можно изменить с помощью модификатора `with blocks`:

```latte
{include 'template.latte' with blocks}
```

Связь между именем файла, указанным в теге, и файлом на диске зависит от [загрузчика |extending-latte#Loaders].


`{sandbox}`
-----------

При включении шаблона, созданного конечным пользователем, следует рассмотреть возможность его "песочницы" (более подробная информация в [документации по "песочнице" |sandbox]):

```latte
{sandbox 'untrusted.latte', level: 3, data: $menu}
```


`{block}`
=========

.[note]
См. также [`{block name}` |template-inheritance#Blocks]

Блоки без названия служат для возможности применения [фильтров |syntax#Filters] к части шаблона. Например, можно применить фильтр [полосы |filters#strip], чтобы удалить ненужные пробелы:

```latte
{block|strip}
<ul>
	<li>Hello World</li>
</ul>
{/block}
```


Обработка исключений .[#toc-exception-handling]
===============================================


`{try}`
-------

С помощью этих тегов очень легко создавать надежные шаблоны.

Если при рендеринге блока `{try}` возникает исключение, весь блок отбрасывается, и рендеринг будет продолжен после него:

```latte
{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
{/try}
```

Содержимое необязательного пункта `{else}` выводится только при возникновении исключения:

```latte
{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
	{else}
	<p>Sorry, the tweets could not be loaded.</p>
{/try}
```

Тег также может быть записан как [n:attribute |syntax#n-attributes]:

```latte
<ul n:try>
	...
</ul>
```

Также можно определить [собственный обработчик исключений |develop#Exception-Handler] для ведения журнала:


`{rollback}`
------------

Блок `{try}` также можно остановить и пропустить вручную с помощью `{rollback}`. Таким образом, вам не нужно проверять все входные данные заранее, и только во время рендеринга вы можете решить, имеет ли смысл рендерить объект.

```latte
{try}
<ul>
	{foreach $people as $person}
 		{skipIf $person->age < 18}
 		<li>{$person->name}</li>
	{else}
		{rollback}
	{/foreach}
</ul>
{/try}
```


Переменные .[#toc-variables]
============================


`{var}` `{default}`
-------------------

Мы создадим новые переменные в шаблоне с помощью тега `{var}`:

```latte
{var $name = 'John Smith'}
{var $age = 27}

{* Multiple declaration *}
{var $name = 'John Smith', $age = 27}
```

Тег `{default}` работает аналогично, за исключением того, что он создает переменные, только если они не существуют:

```latte
{default $lang = 'cs'}
```

Также можно указать [типы переменных |type-system]. Пока они носят информационный характер, и Latte их не проверяет.

```latte
{var string $name = $article->getTitle()}
{default int $id = 0}
```


`{parameters}`
--------------

Подобно тому, как функция объявляет свои параметры, шаблон может объявить свои переменные в самом начале:

```latte
{parameters
	$a,
	?int $b,
	int|string $c = 10
}
```

Переменные `$a` и `$b` без значения по умолчанию автоматически имеют значение по умолчанию `null`. Объявленные типы остаются информативными, и Latte не проверяет их.

В остальном объявленные переменные не передаются в шаблон. Это отличие от тега `{default}`.


`{capture}`
-----------

Используя тег `{capture}`, вы можете захватить вывод в переменную:

```latte
{capture $var}
<ul>
	<li>Hello World</li>
</ul>
{/capture}

<p>Captured: {$var}</p>
```

Метка также может быть записана как [n:attribute |syntax#n:attributes], как и любая парная метка:

```latte
<ul n:capture="$var">
	<li>Hello World</li>
</ul>
```

Чтобы [избежать нежелательного экранирования |develop#disabling-auto-escaping-of-variable] при печати, HTML-вывод хранится в переменной `$var` как объект `Latte\Runtime\Html`.


Другие .[#toc-others]
=====================


`{contentType}`
---------------

Используйте тег, чтобы указать, какой тип содержимого представляет шаблон. Возможны следующие варианты:

- `html` (тип по умолчанию)
- `xml`
- `javascript`
- `css`
- `calendar` (iCal)
- `text`

Его использование важно, поскольку он устанавливает [контекстно-зависимую экранировку |safety-first#Context-Aware-Escaping], и только после этого Latte может правильно экранировать. Например, `{contentType xml}` переключается в режим XML, `{contentType text}` полностью отключает экранирование.

Если параметр является полнофункциональным MIME-типом, например, `application/xml`, он также посылает браузеру HTTP-заголовок `Content-Type`:

```latte
{contentType application/xml}
<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>RSS feed</title>
		<item>
			...
		</item>
	</channel>
</rss>
```


`{debugbreak}`
--------------

Указывает место, где выполнение кода прервется. Используется в целях отладки, чтобы программист мог проверить среду выполнения и убедиться, что код выполняется так, как ожидалось. Поддерживается [Xdebug |https://xdebug.org]. Кроме того, можно указать условие, при котором код должен прерваться.

```latte
{debugbreak}                {* breaks the program *}

{debugbreak $counter == 1}  {* breaks the program if the condition is met *}
```


`{do}`
------

Выполняет PHP-код и ничего не печатает. Как и все остальные теги, PHP-код представляет собой одно выражение, см. [ограничения PHP |syntax#PHP Limitations in Latte].

```latte
{do $num++}
```


`{dump}`
--------

Выгружает переменную или текущий контекст.

```latte
{dump $name} {* dumps the $name variable *}

{dump}       {* dumps all the defined variables *}
```

.[caution]
Требуется пакет [Tracy |tracy:].


`{php}`
-------

Позволяет выполнить любой PHP-код. Тег должен быть активирован с помощью расширения [RawPhpExtension |develop#RawPhpExtension].


`{spaceless}`
-------------

Удаляет ненужные пробельные символы. Аналогичен фильтру [без пробелов |filters#spaceless].

```latte
{spaceless}
	<ul>
		<li>Hello</li>
	</ul>
{/spaceless}
```

Выходные данные:

```latte
<ul> <li>Hello</li> </ul>
```

Тег также может быть записан как [n:attribute |syntax#n-attributes]:


`{syntax}`
----------

Теги Latte не обязательно должны быть заключены только в одинарные фигурные скобки. Вы можете выбрать другой разделитель, даже во время выполнения. Это делается с помощью `{syntax…}`, где параметр может быть:

- double: `{{...}}`
- off: полностью отключает теги Latte

Используя нотацию n:attribute, мы можем отключить Latte только для блока JavaScript:

```latte
<script n:syntax="off">
	var obj = {var: 123}; // this isn't a tag any more
</script>
```

Latte можно очень удобно использовать внутри JavaScript, только избегайте конструкций, как в этом примере, где буква сразу следует за `{`, см. [Latte внутри JavaScript или CSS |recipes#Latte-Inside-JavaScript-or-CSS].

Если вы отключите Latte с помощью `{syntax off}` (т.е. тега, а не атрибута n:attribute), то он будет строго игнорировать все теги до `{/syntax}`.


{trace}
-------

Выбрасывает исключение `Latte\RuntimeException`, стековая трассировка которого выполнена в духе шаблонов. Таким образом, вместо вызова функций и методов, оно включает вызов блоков и вставку шаблонов. Если вы используете инструмент для наглядного отображения брошенных исключений, такой как [Tracy |tracy:], вы будете четко видеть стек вызова, включая все переданные аргументы.


Помощники тегов HTML .[#toc-html-tag-helpers]
=============================================


n:класс .[#toc-n-class]
-----------------------

Благодаря `n:class` очень легко сгенерировать HTML-атрибут `class` именно так, как вам нужно.

Пример: Мне нужно, чтобы активный элемент имел класс `active`:

```latte
{foreach $items as $item}
	<a n:class="$item->isActive() ? active">...</a>
{/foreach}
```

И еще мне нужно, чтобы первый элемент имел классы `first` и `main`:

```latte
{foreach $items as $item}
	<a n:class="$item->isActive() ? active, $iterator->first ? 'first main'">...</a>
{/foreach}
```

А все элементы должны иметь класс `list-item`:

```latte
{foreach $items as $item}
	<a n:class="$item->isActive() ? active, $iterator->first ? 'first main', list-item">...</a>
{/foreach}
```

Удивительно просто, не правда ли?


n:attr .[#toc-n-attr]
---------------------

Атрибут `n:attr` может генерировать произвольные HTML-атрибуты с той же элегантностью, что и [n:class |#n-class].

```latte
{foreach $data as $item}
	<input type="checkbox" n:attr="value: $item->getValue(), checked: $item->isActive()">
{/foreach}
```

В зависимости от возвращаемых значений, он отображает, например:

```latte
<input type="checkbox">

<input type="checkbox" value="Hello">

<input type="checkbox" value="Hello" checked>
```


n:tag
-----

Атрибут `n:tag` может динамически изменять имя элемента HTML.

```latte
<h1 n:tag="$heading" class="main">{$title}</h1>
```

Если `$heading === null`, то `<h1>` тег выводится без изменений. В противном случае имя элемента изменяется на значение переменной, так что для `$heading === 'h3'` записывается:

```latte
<h3 class="main">...</h3>
```

Поскольку Latte является безопасной системой шаблонизации, она проверяет, что имя нового тега является корректным и не содержит никаких нежелательных или вредоносных значений.


n:ifcontent .[#toc-n-ifcontent]
-------------------------------

Предотвращает печать пустого HTML-элемента, т.е. элемента, не содержащего ничего, кроме пробелов.

```latte
<div>
	<div class="error" n:ifcontent>{$error}</div>
</div>
```

В зависимости от значений переменной `$error` будет выводиться:

```latte
{* $error = '' *}
<div>
</div>

{* $error = 'Required' *}
<div>
	<div class="error">Required</div>
</div>
```


Перевод .[#toc-translation]
===========================

Чтобы теги перевода работали, необходимо [настроить переводчик |develop#TranslatorExtension]. Вы также можете использовать [`translate` |filters#translate] фильтр для перевода.


`{_...}`
--------

Переводит значения на другие языки.

```latte
<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
```

Переводчику могут быть переданы и другие параметры:

```latte
<a href="basket">{_'Basket', domain: order}</a>
```


`{translate}`
-------------

Překládá části šablony:

```latte
<h1>{translate}Order{/translate}</h1>

{translate domain: order}Lorem ipsum ...{/translate}
```

Тег также может быть записан как [n:attribute |syntax#n-attributes], чтобы перевести внутреннюю часть элемента:

```latte
<h1 n:translate>Order</h1>
```

Теги Latte

Сводка и описание всех встроенных тегов Latte.

Печать
{$var}, {...} или {=...} печатает экранированную переменную или выражение
{$var|filter} печатает с фильтрами
{l} или {r} печатает символ { or }
Условия
{if}{elseif}{else}{/if} условие if
{ifset}{elseifset}{/ifset} условие ifset
{ifchanged}{/ifchanged} проверка наличия изменений
{switch} {case} {default} {/switch} условие switch
n:else альтернативное содержание условий
Loops
{foreach}{/foreach} foreach
{for}{/for} for
{while}{/while} while
{continueIf $cond} перейти к следующей итерации
{skipIf $cond} пропустить текущую итерацию цикла
{breakIf $cond} прервать цикл
{exitIf $cond} ранний выход
{first}{/first} это первая итерация?
{last}{/last} Это последняя итерация?
{sep}{/sep} последует ли следующая итерация?
{iterateWhile}{/iterateWhile} структурированный foreach
$iterator специальная переменная внутри цикла foreach
Включение других шаблонов
{include 'file.latte'} включает шаблон из другого файла
{sandbox 'file.latte'} включает шаблон в режиме песочницы
Блоки, макеты, наследование шаблонов
{block} анонимный блок
{block blockname} определение блока
{define blockname} определение блока для будущего использования
{include blockname} печатает блок
{include blockname from 'file.latte'} печатает блок из файла
{import 'file.latte'} загружает блоки из другого шаблона
{layout 'file.latte'} / {extends} указание файла макета
{embed}{/embed} загружает шаблон или блок и позволяет перезаписывать блоки
{ifset blockname}{/ifset} условие, если блок определен
Обработка исключений
{try}{else}{/try} перехват исключений
{rollback} отбрасывает блок try
Переменные
{var $foo = value} создание переменных
{default $foo = value} значение по умолчанию, когда переменная не объявлена
{parameters} Объявление переменных, типы значений по умолчанию
{capture}{/capture} Захватывает секцию для переменной
Типы
{varType} объявляет тип переменной
{varPrint} предлагает типы переменных
{templateType} объявляет типы переменных с помощью класса
{templatePrint} генерирует класс со свойствами
Перевод
{_string} печатает перевод
{translate}{/translate} переводит содержимое
Другие
{contentType} переключает режим экранирования и отправляет HTTP-заголовок
{debugbreak} устанавливает точку останова в коде
{do} оценивает выражение, не выводя его на печать
{dump} сбрасывает переменные в Tracy Bar
{php} выполняет любой PHP-код
{spaceless}{/spaceless} удаляет ненужные пробельные символы
{syntax} переключает синтаксис во время выполнения программы
{trace} показывает трассировку стека
Помощники HTML тегов
n:class умный атрибут класса
n:attr интеллектуальные атрибуты HTML
n:tag динамическое имя элемента HTML
n:ifcontent Опустить пустой HTML-тег
Доступно только в Nette Framework
n:href ссылка в HTML-элементах <a>
{link} печатает ссылку
{plink} печатает ссылку на ведущего
{control} печатает компонент
{snippet}{/snippet} фрагмент шаблона, который может быть отправлен с помощью AJAX
{snippetArea} конверт сниппетов
{cache}{/cache} кэширует раздел шаблона
Доступно только в Nette Forms
{form}{/form} печатает элемент формы
{label}{/label} печатает метку ввода формы
{input} печатает элемент ввода формы
{inputError} печатает сообщение об ошибке для элемента ввода формы
n:name активирует элемент ввода HTML
{formContainer}{/formContainer} рендеринг контейнера формы

Печать

{$var} {...} {=...}

Latte использует тег {=...} для печати любого выражения на выходе. Если выражение начинается с переменной или вызова функции, то нет необходимости писать знак равенства. Что на практике означает, что его почти никогда не нужно писать:

Name: {$name} {$surname}<br>
Age: {date('Y') - $birth}<br>

Вы можете записать в виде выражения все, что знаете из PHP. Вам просто не нужно учить новый язык. Например:

{='0' . ($num ?? $num * 3) . ', ' . PHP_VERSION}

Пожалуйста, не ищите никакого смысла в предыдущем примере, но если вы его там найдете, напишите нам :-)

Эскейпинг-вывод

Какая самая важная задача системы шаблонов? Избегать дыр в безопасности. И именно это делает Latte, когда вы печатаете что-то на вывод. Он автоматически экранирует все:

<p>{='one < two'}</p>   {* prints: '<p>one &lt; two</p>' *}

Если быть точным, Latte использует контекстно-зависимую экранировку, которая является настолько важной и уникальной особенностью, что мы посвятили ей отдельную главу.

А если вы печатаете HTML-кодированное содержимое из надежного источника? Тогда вы можете легко отключить экранирование:

{$trustedHtmlString|noescape}

Неправильное использование фильтра noescape может привести к XSS-уязвимости! Никогда не используйте его, если вы не абсолютно уверены в том, что вы делаете, и что печатаемая вами строка получена из надежного источника.

Печать в JavaScript

Благодаря контекстно-зависимому экранированию, очень легко печатать переменные в JavaScript, и Latte будет правильно их экранировать.

Переменная не обязательно должна быть строкой, поддерживается любой тип данных, которые затем кодируются как JSON:

{var $foo = ['hello', true, 1]}
<script>
	alert({$foo});
</script>

Генерирует:

<script>
	alert(["hello", true, 1]);
</script>

Это также причина, по которой не заключайте переменную в кавычки: Latte добавляет их вокруг строк. А если вы хотите поместить строковую переменную в другую строку, просто конкатенируйте их:

<script>
	alert('Hello ' + {$name} + '!');  // OK

	alert({="Hello $name!"});         // OK

	alert('Hello {$name} !');         // ERROR!
</script>

Фильтры

Печатное выражение может быть изменено с помощью фильтров. Например, в этом примере строка преобразуется в верхний регистр и сокращается максимум до 30 символов:

{$string|upper|truncate:30}

Вы также можете применять фильтры к частям выражения следующим образом:

{$left . ($middle|upper) . $right}

Условия

{if} {elseif} {else}

Условия ведут себя так же, как и их аналоги в PHP. Вы можете использовать те же выражения, которые вы знаете из PHP, вам не нужно изучать новый язык.

{if $product->inStock > Stock::Minimum}
	In stock
{elseif $product->isOnWay()}
	On the way
{else}
	Not available
{/if}

Как и любой парный тег, пара {if} ... {/ if} может быть записана как n:attribute, например:

<p n:if="$count > 0">In stock {$count} items</p>

Знаете ли вы, что к n:attributes можно добавить префикс tag-? Тогда условие будет затрагивать только HTML-теги, а содержимое между ними всегда будет выводиться:

<a href="..." n:tag-if="$clickable">Hello</a>

{* prints 'Hello' when $clickable is falsey *}
{* prints '<a href="...">Hello</a>' when $clickable is truthy *}

Отлично.

n:else

Если условие {if} ... {/if} записано в виде атрибута n:attribute, то у вас есть возможность указать альтернативную ветвь с помощью n:else:

<strong n:if="$count > 0">In stock {$count} items</strong>

<em n:else>not available</em>

Атрибут n:else также может использоваться в сочетании с. n:ifset, n:foreach, n:try, n:ifcontent, и n:ifchanged.

{/if $cond}

Вас может удивить, что выражение в условии {if} также может быть указано в теге end. Это полезно в ситуациях, когда мы еще не знаем значение условия на момент открытия тега. Назовем это отложенным решением.

Например, мы начинаем выводить таблицу с записями из базы данных, и только после завершения отчета понимаем, что в базе данных не было ни одной записи. Поэтому мы помещаем условие в конечный тег {/if}, и если записи нет, то ничего из этого не будет напечатано:

{if}
	<h1>Printing rows from the database</h1>

	<table>
	{foreach $resultSet as $row}
		...
	{/foreach}
	</table>
{/if isset($row)}

Удобно, не правда ли?

Вы также можете использовать {else} в отложенном условии, но не {elseif}.

{ifset} {elseifset}

См. также {ifset block}

Используйте условие {ifset $var}, чтобы определить, существует ли переменная (или несколько переменных) и имеет ли она ненулевое значение. На самом деле это то же самое, что и if (isset($var)) в PHP. Как и любой парный тег, этот может быть записан в виде n:attribute, поэтому покажем его на примере:

<meta name="robots" content={$robots} n:ifset="$robots">

{ifchanged}

{ifchanged} проверяет, изменилось ли значение переменной с момента последней итерации в цикле (foreach, for или while).

Если мы укажем в теге одну или несколько переменных, он проверит, изменилось ли значение любой из них, и напечатает содержимое соответствующим образом. Например, в следующем примере при перечислении имен в качестве заголовка печатается первая буква имени каждый раз, когда она меняется:

{foreach ($names|sort) as $name}
	{ifchanged $name[0]} <h2>{$name[0]}</h2> {/ifchanged}

	<p>{$name}</p>
{/foreach}

Однако, если аргумент не указан, то будет проверено само содержимое рендеринга в соответствии с его предыдущим состоянием. Это означает, что в предыдущем примере мы можем смело опустить аргумент в теге. И, конечно, мы также можем использовать n:attribute:

{foreach ($names|sort) as $name}
	<h2 n:ifchanged>{$name[0]}</h2>

	<p>{$name}</p>
{/foreach}

Вы также можете включить клаузулу {else} внутрь {ifchanged}.

{switch} {case} {default}

Сравнивает значение с несколькими вариантами. Это похоже на структуру switch, известную вам из PHP. Однако Latte улучшает ее:

  • использует строгое сравнение (===)
  • не требует break

Таким образом, это точный эквивалент структуры match, с которой поставляется PHP 8.0.

{switch $transport}
	{case train}
		By train
	{case plane}
		By plane
	{default}
		Differently
{/switch}

Пункт {case} может содержать несколько значений, разделенных запятыми:

{switch $status}
{case $status::New}<b>new item</b>
{case $status::Sold, $status::Unknown}<i>not available</i>
{/switch}

Циклы

В Latte доступны все циклы, знакомые вам по PHP: foreach, for и while.

{foreach}

Вы пишете цикл точно так же, как и в PHP:

{foreach $langs as $code => $lang}
	<span>{$lang}</span>
{/foreach}

Кроме того, у него есть несколько удобных твиков, о которых мы сейчас поговорим.

Например, Latte проверяет, чтобы созданные переменные случайно не перезаписали одноименные глобальные переменные. Это спасет вас, когда вы предполагаете, что $lang – текущий язык страницы, и не понимаете, что foreach $langs as $lang перезаписал эту переменную.

Цикл foreach также может быть написан очень элегантно и экономично с помощью n:attribute:

<ul>
	<li n:foreach="$items as $item">{$item->name}</li>
</ul>

Знаете ли вы, что к n:attributes можно добавлять префикс inner-? Тогда в цикле будет повторяться только внутренняя часть элемента:

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

Таким образом, будет выведено что-то вроде:

<div>
	<h4>Foo</h4>
	<p>Lorem ipsum.</p>
	<h4>Bar</h4>
	<p>Sit dolor.</p>
</div>

{else}

Цикл foreach может принимать необязательное предложение {else}, текст которого выводится, если заданный массив пуст:

<ul>
	{foreach $people as $person}
		<li>{$person->name}</li>
	{else}
		<li><em>Sorry, no users in this list</em></li>
	{/foreach}
</ul>

$iterator

Внутри цикла foreach инициализируется переменная $iterator. В ней хранится важная информация о текущем цикле.

  • $iterator->first – это первая итерация?
  • $iterator->last – это последняя итерация?
  • $iterator->counter – счетчик итераций, начинается с 1
  • $iterator->counter0 – счетчик итераций, начинается с 0
  • $iterator->odd – эта итерация нечетная?
  • $iterator->even – эта итерация четная?
  • $iterator->parent – итератор, окружающий текущий итератор.
  • $iterator->nextValue – следующий элемент в цикле
  • $iterator->nextKey – ключ следующего элемента в цикле
{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}

Лата умница и $iterator->last работает не только для массивов, но и когда цикл работает над общим итератором, где количество элементов заранее не известно.

{first} {last} {sep}

Эти теги можно использовать внутри цикла {foreach}. Содержимое {first} отображается при первом проходе. Содержимое {last} отображается … можете догадаться? Да, для последнего прохода. На самом деле это ярлыки для {if $iterator->first} и {if $iterator->last}.

Теги также могут быть записаны как n:attributes:

{foreach $rows as $row}
	{first}<h1>List of names</h1>{/first}

	<p>{$row->name}</p>

	<hr n:last>
{/foreach}

Содержимое {sep} выводится, если итерация не последняя, поэтому он подходит для печати разделителей, например, запятых между элементами списка:

{foreach $items as $item} {$item} {sep}, {/sep} {/foreach}

Это довольно практично, не так ли?

{iterateWhile}

Упрощает группировку линейных данных во время итерации в цикле foreach, выполняя итерацию во вложенном цикле до тех пор, пока не будет выполнено условие. Ознакомьтесь с подробными инструкциями.

Он также может элегантно заменить {first} и {last} в примере выше:

{foreach $rows as $row}
	<table>

	{iterateWhile}
	<tr id="row-{$iterator->counter}">
		<td>{$row->name}</td>
		<td>{$row->email}</td>
	</tr>
	{/iterateWhile true}

	</table>
{/foreach}

См. также пакетные и групповые фильтры.

{for}

Мы пишем цикл точно так же, как и в PHP:

{for $i = 0; $i < 10; $i++}
	<span>Item #{$i}</span>
{/for}

Тег также может быть записан как n:attribute:

<h1 n:for="$i = 0; $i < 10; $i++">{$i}</h1>

{while}

Опять же, мы пишем цикл точно так же, как и в PHP:

{while $row = $result->fetch()}
	<span>{$row->title}</span>
{/while}

Или как n:attribute:

<span n:while="$row = $result->fetch()">
	{$row->title}
</span>

Вариант с условием в конце тега соответствует циклу do-while в PHP:

{while}
	<span>{$item->title}</span>
{/while $item = $item->getNext()}

{continueIf} {skipIf} {breakIf}

Существуют специальные теги, которые можно использовать для управления любым циклом – {continueIf ?} и {breakIf ?}, которые переходят к следующей итерации и завершают цикл, соответственно, при выполнении условий:

{foreach $rows as $row}
	{continueIf $row->date < $now}
	{breakIf $row->parent === null}
	...
{/foreach}

Тег {skipIf} очень похож на {continueIf}, но не увеличивает счетчик. Таким образом, при печати $iterator->counter и пропуске некоторых элементов в нумерации не будет дыр. Также предложение {else} будет выведено при пропуске всех элементов.

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

Завершает отрисовку шаблона или блока при выполнении условия.

{exitIf !$messages}

<h1>Messages</h1>
<div n:foreach="$messages as $message">
   {$message}
</div>

Включение шаблонов

{include 'file.latte'}

См. также {include block}

Тег {include} загружает и отображает указанный шаблон. На нашем любимом языке PHP это выглядит так:

<?php include 'header.phtml'; ?>

Включенные шаблоны не имеют доступа к переменным активного контекста, но имеют доступ к глобальным переменным.

Вы можете передавать переменные вставленному шаблону следующим образом:

{include 'template.latte', foo: 'bar', id: 123}

Имя шаблона может быть любым выражением PHP:

{include $someVar}
{include $ajax ? 'ajax.latte' : 'not-ajax.latte'}

Вставленное содержимое может быть изменено с помощью фильтров. В следующем примере удаляется весь HTML и корректируется регистр:

<title>{include 'heading.latte' |stripHtml|capitalize}</title>

По умолчанию наследование шаблона не участвует в этом. Хотя вы можете добавлять теги блоков в включаемые шаблоны, они не будут заменять соответствующие блоки в шаблоне, в который они включены. Рассматривайте включаемые блоки как независимые и экранированные части страниц или модулей. Это поведение можно изменить с помощью модификатора with blocks:

{include 'template.latte' with blocks}

Связь между именем файла, указанным в теге, и файлом на диске зависит от загрузчика.

{sandbox}

При включении шаблона, созданного конечным пользователем, следует рассмотреть возможность его „песочницы“ (более подробная информация в документации по „песочнице“):

{sandbox 'untrusted.latte', level: 3, data: $menu}

{block}

См. также {block name}

Блоки без названия служат для возможности применения фильтров к части шаблона. Например, можно применить фильтр полосы, чтобы удалить ненужные пробелы:

{block|strip}
<ul>
	<li>Hello World</li>
</ul>
{/block}

Обработка исключений

{try}

С помощью этих тегов очень легко создавать надежные шаблоны.

Если при рендеринге блока {try} возникает исключение, весь блок отбрасывается, и рендеринг будет продолжен после него:

{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
{/try}

Содержимое необязательного пункта {else} выводится только при возникновении исключения:

{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
	{else}
	<p>Sorry, the tweets could not be loaded.</p>
{/try}

Тег также может быть записан как n:attribute:

<ul n:try>
	...
</ul>

Также можно определить собственный обработчик исключений для ведения журнала:

{rollback}

Блок {try} также можно остановить и пропустить вручную с помощью {rollback}. Таким образом, вам не нужно проверять все входные данные заранее, и только во время рендеринга вы можете решить, имеет ли смысл рендерить объект.

{try}
<ul>
	{foreach $people as $person}
 		{skipIf $person->age < 18}
 		<li>{$person->name}</li>
	{else}
		{rollback}
	{/foreach}
</ul>
{/try}

Переменные

{var} {default}

Мы создадим новые переменные в шаблоне с помощью тега {var}:

{var $name = 'John Smith'}
{var $age = 27}

{* Multiple declaration *}
{var $name = 'John Smith', $age = 27}

Тег {default} работает аналогично, за исключением того, что он создает переменные, только если они не существуют:

{default $lang = 'cs'}

Также можно указать типы переменных. Пока они носят информационный характер, и Latte их не проверяет.

{var string $name = $article->getTitle()}
{default int $id = 0}

{parameters}

Подобно тому, как функция объявляет свои параметры, шаблон может объявить свои переменные в самом начале:

{parameters
	$a,
	?int $b,
	int|string $c = 10
}

Переменные $a и $b без значения по умолчанию автоматически имеют значение по умолчанию null. Объявленные типы остаются информативными, и Latte не проверяет их.

В остальном объявленные переменные не передаются в шаблон. Это отличие от тега {default}.

{capture}

Используя тег {capture}, вы можете захватить вывод в переменную:

{capture $var}
<ul>
	<li>Hello World</li>
</ul>
{/capture}

<p>Captured: {$var}</p>

Метка также может быть записана как n:attribute, как и любая парная метка:

<ul n:capture="$var">
	<li>Hello World</li>
</ul>

Чтобы избежать нежелательного экранирования при печати, HTML-вывод хранится в переменной $var как объект Latte\Runtime\Html.

Другие

{contentType}

Используйте тег, чтобы указать, какой тип содержимого представляет шаблон. Возможны следующие варианты:

  • html (тип по умолчанию)
  • xml
  • javascript
  • css
  • calendar (iCal)
  • text

Его использование важно, поскольку он устанавливает контекстно-зависимую экранировку, и только после этого Latte может правильно экранировать. Например, {contentType xml} переключается в режим XML, {contentType text} полностью отключает экранирование.

Если параметр является полнофункциональным MIME-типом, например, application/xml, он также посылает браузеру HTTP-заголовок Content-Type:

{contentType application/xml}
<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>RSS feed</title>
		<item>
			...
		</item>
	</channel>
</rss>

{debugbreak}

Указывает место, где выполнение кода прервется. Используется в целях отладки, чтобы программист мог проверить среду выполнения и убедиться, что код выполняется так, как ожидалось. Поддерживается Xdebug. Кроме того, можно указать условие, при котором код должен прерваться.

{debugbreak}                {* breaks the program *}

{debugbreak $counter == 1}  {* breaks the program if the condition is met *}

{do}

Выполняет PHP-код и ничего не печатает. Как и все остальные теги, PHP-код представляет собой одно выражение, см. ограничения PHP.

{do $num++}

{dump}

Выгружает переменную или текущий контекст.

{dump $name} {* dumps the $name variable *}

{dump}       {* dumps all the defined variables *}

Требуется пакет Tracy.

{php}

Позволяет выполнить любой PHP-код. Тег должен быть активирован с помощью расширения RawPhpExtension.

{spaceless}

Удаляет ненужные пробельные символы. Аналогичен фильтру без пробелов.

{spaceless}
	<ul>
		<li>Hello</li>
	</ul>
{/spaceless}

Выходные данные:

<ul> <li>Hello</li> </ul>

Тег также может быть записан как n:attribute:

{syntax}

Теги Latte не обязательно должны быть заключены только в одинарные фигурные скобки. Вы можете выбрать другой разделитель, даже во время выполнения. Это делается с помощью {syntax…}, где параметр может быть:

  • double: {{...}}
  • off: полностью отключает теги Latte

Используя нотацию n:attribute, мы можем отключить Latte только для блока JavaScript:

<script n:syntax="off">
	var obj = {var: 123}; // this isn't a tag any more
</script>

Latte можно очень удобно использовать внутри JavaScript, только избегайте конструкций, как в этом примере, где буква сразу следует за {, см. Latte внутри JavaScript или CSS.

Если вы отключите Latte с помощью {syntax off} (т.е. тега, а не атрибута n:attribute), то он будет строго игнорировать все теги до {/syntax}.

{trace}

Выбрасывает исключение Latte\RuntimeException, стековая трассировка которого выполнена в духе шаблонов. Таким образом, вместо вызова функций и методов, оно включает вызов блоков и вставку шаблонов. Если вы используете инструмент для наглядного отображения брошенных исключений, такой как Tracy, вы будете четко видеть стек вызова, включая все переданные аргументы.

Помощники тегов HTML

n:класс

Благодаря n:class очень легко сгенерировать HTML-атрибут class именно так, как вам нужно.

Пример: Мне нужно, чтобы активный элемент имел класс active:

{foreach $items as $item}
	<a n:class="$item->isActive() ? active">...</a>
{/foreach}

И еще мне нужно, чтобы первый элемент имел классы first и main:

{foreach $items as $item}
	<a n:class="$item->isActive() ? active, $iterator->first ? 'first main'">...</a>
{/foreach}

А все элементы должны иметь класс list-item:

{foreach $items as $item}
	<a n:class="$item->isActive() ? active, $iterator->first ? 'first main', list-item">...</a>
{/foreach}

Удивительно просто, не правда ли?

n:attr

Атрибут n:attr может генерировать произвольные HTML-атрибуты с той же элегантностью, что и n:class.

{foreach $data as $item}
	<input type="checkbox" n:attr="value: $item->getValue(), checked: $item->isActive()">
{/foreach}

В зависимости от возвращаемых значений, он отображает, например:

<input type="checkbox">

<input type="checkbox" value="Hello">

<input type="checkbox" value="Hello" checked>

n:tag

Атрибут n:tag может динамически изменять имя элемента HTML.

<h1 n:tag="$heading" class="main">{$title}</h1>

Если $heading === null, то <h1> тег выводится без изменений. В противном случае имя элемента изменяется на значение переменной, так что для $heading === 'h3' записывается:

<h3 class="main">...</h3>

Поскольку Latte является безопасной системой шаблонизации, она проверяет, что имя нового тега является корректным и не содержит никаких нежелательных или вредоносных значений.

n:ifcontent

Предотвращает печать пустого HTML-элемента, т.е. элемента, не содержащего ничего, кроме пробелов.

<div>
	<div class="error" n:ifcontent>{$error}</div>
</div>

В зависимости от значений переменной $error будет выводиться:

{* $error = '' *}
<div>
</div>

{* $error = 'Required' *}
<div>
	<div class="error">Required</div>
</div>

Перевод

Чтобы теги перевода работали, необходимо настроить переводчик. Вы также можете использовать translate фильтр для перевода.

{_...}

Переводит значения на другие языки.

<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>

Переводчику могут быть переданы и другие параметры:

<a href="basket">{_'Basket', domain: order}</a>

{translate}

Překládá části šablony:

<h1>{translate}Order{/translate}</h1>

{translate domain: order}Lorem ipsum ...{/translate}

Тег также может быть записан как n:attribute, чтобы перевести внутреннюю часть элемента:

<h1 n:translate>Order</h1>