Nette Documentation Preview

syntax
Синтаксис
*********

.[perex]
Синтаксис Latte возник из практических требований веб-дизайнеров. Мы искали самый удобный синтаксис, с помощью которого можно элегантно записывать даже конструкции, которые в противном случае представляют собой настоящую головоломку. В то же время все выражения пишутся точно так же, как в PHP, так что вам не придется учить новый язык. Вы просто используете то, что уже давно умеете.

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

```latte
{* это комментарий *}
<ul n:if=$items>                  {* n:if - это n:атрибут *}
{foreach $items as $item}         {* тег, представляющий цикл foreach *}
	<li>{$item|capitalize}</li>   {* тег, выводящий переменную с фильтром *}
{/foreach}                        {* конец цикла *}
</ul>
```

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


Теги
====

Шаблон содержит теги, которые управляют логикой шаблона (например, циклы *foreach*) или выводят выражения. Для обоих используется единый разделитель `{ ... }`, так что вам не нужно думать, какой разделитель использовать в какой ситуации, как это бывает в других системах. Если за символом `{` следует кавычка или пробел, Latte не считает его началом тега, благодаря чему вы можете без проблем использовать в шаблонах и JavaScript-конструкции, JSON или правила в CSS.

Посмотрите [обзор всех тегов |tags]. Кроме того, вы можете создавать и [пользовательские теги |custom tags].


Latte понимает PHP
==================

Внутри тегов вы можете использовать PHP-выражения, которые вам хорошо знакомы:

- переменные
- строки (включая HEREDOC и NOWDOC), массивы, числа и т.д.
- [операторы |https://www.php.net/manual/en/language.operators.php]
- вызовы функций и методов (которые можно ограничить [песочницей |sandbox])
- [match |https://www.php.net/manual/en/control-structures.match.php]
- [анонимные функции |https://www.php.net/manual/en/functions.arrow.php]
- [коллбэки |https://www.php.net/manual/en/functions.first_class_callable_syntax.php]
- многострочные комментарии `/* ... */`
- и т.д…

Кроме того, Latte дополняет синтаксис PHP несколькими [приятными расширениями |#Синтаксический сахар].


n:атрибуты
==========

Все парные теги, например `{if} … {/if}`, оперирующие над одним HTML-элементом, можно переписать в виде n:атрибутов. Так можно было бы записать, например, и `{foreach}` во вводном примере:

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

Функциональность тогда относится к HTML-элементу, в который она помещена:

```latte
{var $items = ['I', '♥', 'Latte']}

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

выводит:

```latte
<p>I</p>
<p>♥</p>
<p>Latte</p>
```

С помощью префикса `inner-` мы можем изменить поведение так, чтобы оно относилось только к внутренней части элемента:

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

Выведется:

```latte
<div>
	<p>I</p>
	<hr>
	<p>♥</p>
	<hr>
	<p>Latte</p>
	<hr>
</div>
```

Или с помощью префикса `tag-` применим функциональность только к самим HTML-тегам:

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

Что выведет в зависимости от переменной `$url`:

```latte
{* когда $url пуст *}
<p>Title</p>

{* когда $url содержит 'https://nette.org' *}
<p><a href="https://nette.org">Title</a></p>
```

Однако n:атрибуты — это не просто сокращение для парных тегов. Существуют и чистые n:атрибуты, такие как [n:href |application:creating-links#В шаблоне презентера] или очень удобный помощник кодера [n:class |tags#n:class].


Фильтры
=======

Посмотрите обзор [стандартных фильтров |filters].

Фильтры записываются после вертикальной черты (перед ней может быть пробел):

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

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

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

Параметры указываются после имени фильтра, разделенные двоеточиями или запятыми:

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

Фильтры можно применять и к выражению:

```latte
{var $name = ($title|upper) . ($subtitle|lower)}
```

К блоку:

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

Или непосредственно к значению (в сочетании с тегом [`{=expr}` |tags#Вывод]):
```latte
<h1>{='  Hello world  '|trim}<h1>
```


Динамические HTML-теги .{data-version:3.0.9}
============================================

Latte поддерживает динамические HTML-теги, которые полезны, когда вам нужна гибкость в именах тегов:

```latte
<h{$level}>Heading</h{$level}>
```

Приведенный выше код может, например, генерировать `<h1>Heading</h1>` или `<h2>Heading</h2>` в зависимости от значения переменной `$level`. Динамические HTML-теги в Latte всегда должны быть парными. Их альтернативой является [n:tag |tags#n:tag].

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


Комментарии
===========

Комментарии записываются таким образом и в вывод не попадают:

```latte
{* это комментарий в Latte *}
```

Внутри тегов работают PHP-комментарии:

```latte
{include 'file.info', /* value: 123 */}
```


Синтаксический сахар
====================


Строки без кавычек
------------------

Для простых строк можно опускать кавычки:

```latte
как в PHP:  {var $arr = ['hello', 'btn--default', '€']}

сокращенно:    {var $arr = [hello, btn--default, €]}
```

Простые строки — это те, которые состоят исключительно из букв, цифр, подчеркиваний, дефисов и точек. Они не должны начинаться с цифры и не должны начинаться или заканчиваться дефисом. Они не должны состоять только из заглавных букв и подчеркиваний, потому что тогда они считаются константами (например, `PHP_VERSION`). И они не должны конфликтовать с ключевыми словами: `and`, `array`, `clone`, `default`, `false`, `in`, `instanceof`, `new`, `null`, `or`, `return`, `true`, `xor`.


Константы
---------

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

```latte
{if \PROJECT_ID === 1} ... {/if}
```

Эта запись полностью валидна в самом PHP, косая черта говорит о том, что константа находится в глобальном пространстве имен.


Сокращенный тернарный оператор
------------------------------

Если третье значение тернарного оператора пустое, его можно опустить:

```latte
как в PHP:  {$stock ? 'В наличии' : ''}

сокращенно:    {$stock ? 'В наличии'}
```


Современная запись ключей в массиве
-----------------------------------

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

```latte
как в PHP:  {var $arr = ['one' => 'item 1', 'two' => 'item 2']}

современно:     {var $arr = [one: 'item 1', two: 'item 2']}
```


Фильтры
-------

Фильтры можно применять к любым выражениям, достаточно заключить целое в скобки:

```latte
{var $content = ($text|truncate: 30|upper)}
```


Оператор `in`
-------------

Оператором `in` можно заменить функцию `in_array()`. Сравнение всегда строгое:

```latte
{* аналог in_array($item, $items, true) *}
{if $item in $items}
	...
{/if}
```


Исторический экскурс
--------------------

Latte в ходе своей истории представило целый ряд синтаксических улучшений, которые через несколько лет появились в самом PHP. Например, в Latte можно было писать массивы как `[1, 2, 3]` вместо `array(1, 2, 3)` или использовать nullsafe оператор `$obj?->foo` задолго до того, как это стало возможным в самом PHP. Latte также ввело оператор распаковки массива `(expand) $arr`, который является эквивалентом сегодняшнего оператора `...$arr` из PHP.

Undefined-safe оператор `??->`, который является аналогом nullsafe оператора `?->`, но не вызывает ошибку, если переменная не существует, возник по историческим причинам, и сегодня мы рекомендуем использовать стандартный PHP-оператор `?->`.


Ограничения PHP в Latte
=======================

В Latte можно записывать только PHP-выражения. То есть нельзя использовать инструкции, заканчивающиеся точкой с запятой. Нельзя объявлять классы или использовать [управляющие структуры |https://www.php.net/manual/en/language.control-structures.php], например `if`, `foreach`, `switch`, `return`, `try`, `throw` и другие, вместо которых Latte предлагает свои [теги |tags]. Также нельзя использовать [атрибуты |https://www.php.net/manual/en/language.attributes.php], [обратные кавычки |https://www.php.net/manual/en/language.operators.execution.php] или некоторые [магические константы |https://www.php.net/manual/en/language.constants.magic.php]. Нельзя использовать и `unset`, `echo`, `include`, `require`, `exit`, `eval`, потому что это не функции, а специальные языковые конструкции PHP, и они не являются выражениями. Комментарии поддерживаются только многострочные `/* ... */`.

Однако эти ограничения можно обойти, активировав расширение [RawPhpExtension |develop#RawPhpExtension], благодаря которому можно затем использовать в теге `{php ...}` любой PHP-код под ответственность автора шаблона.

Синтаксис

Синтаксис Latte возник из практических требований веб-дизайнеров. Мы искали самый удобный синтаксис, с помощью которого можно элегантно записывать даже конструкции, которые в противном случае представляют собой настоящую головоломку. В то же время все выражения пишутся точно так же, как в PHP, так что вам не придется учить новый язык. Вы просто используете то, что уже давно умеете.

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

{* это комментарий *}
<ul n:if=$items>                  {* n:if - это n:атрибут *}
{foreach $items as $item}         {* тег, представляющий цикл foreach *}
	<li>{$item|capitalize}</li>   {* тег, выводящий переменную с фильтром *}
{/foreach}                        {* конец цикла *}
</ul>

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

Теги

Шаблон содержит теги, которые управляют логикой шаблона (например, циклы foreach) или выводят выражения. Для обоих используется единый разделитель { ... }, так что вам не нужно думать, какой разделитель использовать в какой ситуации, как это бывает в других системах. Если за символом { следует кавычка или пробел, Latte не считает его началом тега, благодаря чему вы можете без проблем использовать в шаблонах и JavaScript-конструкции, JSON или правила в CSS.

Посмотрите обзор всех тегов. Кроме того, вы можете создавать и пользовательские теги.

Latte понимает PHP

Внутри тегов вы можете использовать PHP-выражения, которые вам хорошо знакомы:

Кроме того, Latte дополняет синтаксис PHP несколькими приятными расширениями.

n:атрибуты

Все парные теги, например {if} … {/if}, оперирующие над одним HTML-элементом, можно переписать в виде n:атрибутов. Так можно было бы записать, например, и {foreach} во вводном примере:

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

Функциональность тогда относится к HTML-элементу, в который она помещена:

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

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

выводит:

<p>I</p>
<p>♥</p>
<p>Latte</p>

С помощью префикса inner- мы можем изменить поведение так, чтобы оно относилось только к внутренней части элемента:

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

Выведется:

<div>
	<p>I</p>
	<hr>
	<p>♥</p>
	<hr>
	<p>Latte</p>
	<hr>
</div>

Или с помощью префикса tag- применим функциональность только к самим HTML-тегам:

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

Что выведет в зависимости от переменной $url:

{* когда $url пуст *}
<p>Title</p>

{* когда $url содержит 'https://nette.org' *}
<p><a href="https://nette.org">Title</a></p>

Однако n:атрибуты — это не просто сокращение для парных тегов. Существуют и чистые n:атрибуты, такие как n:href или очень удобный помощник кодера n:class.

Фильтры

Посмотрите обзор стандартных фильтров.

Фильтры записываются после вертикальной черты (перед ней может быть пробел):

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

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

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

Параметры указываются после имени фильтра, разделенные двоеточиями или запятыми:

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

Фильтры можно применять и к выражению:

{var $name = ($title|upper) . ($subtitle|lower)}

К блоку:

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

Или непосредственно к значению (в сочетании с тегом {=expr}):

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

Динамические HTML-теги

Latte поддерживает динамические HTML-теги, которые полезны, когда вам нужна гибкость в именах тегов:

<h{$level}>Heading</h{$level}>

Приведенный выше код может, например, генерировать <h1>Heading</h1> или <h2>Heading</h2> в зависимости от значения переменной $level. Динамические HTML-теги в Latte всегда должны быть парными. Их альтернативой является n:tag.

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

Комментарии

Комментарии записываются таким образом и в вывод не попадают:

{* это комментарий в Latte *}

Внутри тегов работают PHP-комментарии:

{include 'file.info', /* value: 123 */}

Синтаксический сахар

Строки без кавычек

Для простых строк можно опускать кавычки:

как в PHP:  {var $arr = ['hello', 'btn--default', '€']}

сокращенно:    {var $arr = [hello, btn--default, €]}

Простые строки — это те, которые состоят исключительно из букв, цифр, подчеркиваний, дефисов и точек. Они не должны начинаться с цифры и не должны начинаться или заканчиваться дефисом. Они не должны состоять только из заглавных букв и подчеркиваний, потому что тогда они считаются константами (например, PHP_VERSION). И они не должны конфликтовать с ключевыми словами: and, array, clone, default, false, in, instanceof, new, null, or, return, true, xor.

Константы

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

{if \PROJECT_ID === 1} ... {/if}

Эта запись полностью валидна в самом PHP, косая черта говорит о том, что константа находится в глобальном пространстве имен.

Сокращенный тернарный оператор

Если третье значение тернарного оператора пустое, его можно опустить:

как в PHP:  {$stock ? 'В наличии' : ''}

сокращенно:    {$stock ? 'В наличии'}

Современная запись ключей в массиве

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

как в PHP:  {var $arr = ['one' => 'item 1', 'two' => 'item 2']}

современно:     {var $arr = [one: 'item 1', two: 'item 2']}

Фильтры

Фильтры можно применять к любым выражениям, достаточно заключить целое в скобки:

{var $content = ($text|truncate: 30|upper)}

Оператор in

Оператором in можно заменить функцию in_array(). Сравнение всегда строгое:

{* аналог in_array($item, $items, true) *}
{if $item in $items}
	...
{/if}

Исторический экскурс

Latte в ходе своей истории представило целый ряд синтаксических улучшений, которые через несколько лет появились в самом PHP. Например, в Latte можно было писать массивы как [1, 2, 3] вместо array(1, 2, 3) или использовать nullsafe оператор $obj?->foo задолго до того, как это стало возможным в самом PHP. Latte также ввело оператор распаковки массива (expand) $arr, который является эквивалентом сегодняшнего оператора ...$arr из PHP.

Undefined-safe оператор ??->, который является аналогом nullsafe оператора ?->, но не вызывает ошибку, если переменная не существует, возник по историческим причинам, и сегодня мы рекомендуем использовать стандартный PHP-оператор ?->.

Ограничения PHP в Latte

В Latte можно записывать только PHP-выражения. То есть нельзя использовать инструкции, заканчивающиеся точкой с запятой. Нельзя объявлять классы или использовать управляющие структуры, например if, foreach, switch, return, try, throw и другие, вместо которых Latte предлагает свои теги. Также нельзя использовать атрибуты, обратные кавычки или некоторые магические константы. Нельзя использовать и unset, echo, include, require, exit, eval, потому что это не функции, а специальные языковые конструкции PHP, и они не являются выражениями. Комментарии поддерживаются только многострочные /* ... */.

Однако эти ограничения можно обойти, активировав расширение RawPhpExtension, благодаря которому можно затем использовать в теге {php ...} любой PHP-код под ответственность автора шаблона.