Nette Documentation Preview

syntax
Znaczniki Latte
***************

.[perex]
Przegląd i opis wszystkich znaczników systemu szablonów Latte, które są standardowo dostępne.

.[table-latte-tags language-latte]
|## Wyświetlanie
| `{$var}`, `{...}` lub `{=...}`  | [wyświetla escapowaną zmienną lub wyrażenie |#Wyświetlanie]
| `{$var\|filter}`                 | [wyświetla z użyciem filtrów |#Filtry]
| `{l}` lub `{r}`                 | wyświetla znak `{` lub `}`

.[table-latte-tags language-latte]
|## Warunki
| `{if}` … `{elseif}` … `{else}` … `{/if}`    | [warunek if |#if elseif else]
| `{ifset}` … `{elseifset}` … `{/ifset}`      | [warunek ifset |#ifset elseifset]
| `{ifchanged}` … `{/ifchanged}`              | [sprawdza, czy nastąpiła zmiana |#ifchanged]
| `{switch}` `{case}` `{default}` `{/switch}` | [warunek switch |#switch case default]
| `n:else`                                    | [alternatywna zawartość dla warunków |#n:else]

.[table-latte-tags language-latte]
|## Pętle
| `{foreach}` … `{/foreach}`     | [#foreach]
| `{for}` … `{/for}`             | [#for]
| `{while}` … `{/while}`         | [#while]
| `{continueIf $cond}`           | [kontynuuj następną iterację |#continueIf skipIf breakIf]
| `{skipIf $cond}`               | [pomiń iterację |#continueIf skipIf breakIf]
| `{breakIf $cond}`              | [przerwanie pętli |#continueIf skipIf breakIf]
| `{exitIf $cond}`               | [wczesne zakończenie |#exitIf]
| `{first}` … `{/first}`         | [czy to pierwsze przejście? |#first last sep]
| `{last}` … `{/last}`           | [czy to ostatnie przejście? |#first last sep]
| `{sep}` … `{/sep}`             | [czy nastąpi kolejne przejście? |#first last sep]
| `{iterateWhile}` … `{/iterateWhile}` | [ustrukturyzowany foreach |#iterateWhile]
| `$iterator`                    | [specjalna zmienna wewnątrz foreach |#iterator]

.[table-latte-tags language-latte]
|## Dołączanie innych szablonów
| `{include 'file.latte'}`       | [wczytuje szablon z innego pliku |#include]
| `{sandbox 'file.latte'}`       | [wczytuje szablon w trybie sandbox |#sandbox]

.[table-latte-tags language-latte]
|## Bloki, layouty, dziedziczenie szablonów
| `{block}`                      | [blok anonimowy |#block]
| `{block blockname}`            | [definiuje blok |template-inheritance#Bloki]
| `{define blockname}`           | [definiuje blok do późniejszego użycia |template-inheritance#Definicje define]
| `{include blockname}`          | [renderowanie bloku |template-inheritance#Renderowanie bloków]
| `{include blockname from 'file.latte'}` | [renderuje blok z pliku |template-inheritance#Renderowanie bloków]
| `{import 'file.latte'}`        | [wczytuje bloki z szablonu |template-inheritance#Ponowne wykorzystanie poziome]
| `{layout 'file.latte'}` / `{extends}` | [określa plik z layoutem |template-inheritance#Dziedziczenie layoutu]
| `{embed}` … `{/embed}`         | [wczytuje szablon lub blok i pozwala nadpisać bloki |template-inheritance#Dziedziczenie jednostkowe]
| `{ifset blockname}` … `{/ifset}`   | [warunek, czy blok istnieje |template-inheritance#Sprawdzanie istnienia bloków]

.[table-latte-tags language-latte]
|## Obsługa wyjątków
| `{try}` … `{else}` … `{/try}`  | [przechwytywanie wyjątków |#try]
| `{rollback}`                   | [odrzucenie bloku try |#rollback]

.[table-latte-tags language-latte]
|## Zmienne
| `{var $foo = value}`           | [tworzy zmienną |#var default]
| `{default $foo = value}`       | [tworzy zmienną, jeśli nie istnieje |#var default]
| `{parameters}`                 | [deklaruje zmienne, typy i wartości domyślne |#parameters]
| `{capture}` … `{/capture}`     | [przechwytuje blok do zmiennej |#capture]

.[table-latte-tags language-latte]
|## Typy
| `{varType}`                    | [deklaruje typ zmiennej |type-system#varType]
| `{varPrint}`                   | [proponuje typy zmiennych |type-system#varPrint]
| `{templateType}`               | [deklaruje typy zmiennych według klasy |type-system#templateType]
| `{templatePrint}`              | [proponuje klasę z typami zmiennych |type-system#templatePrint]

.[table-latte-tags language-latte]
|## Tłumaczenia
| `{_...}`                       | [wyświetla tłumaczenie |#Tłumaczenia]
| `{translate}` … `{/translate}` | [tłumaczy zawartość |#Tłumaczenia]

.[table-latte-tags language-latte]
|## Inne
| `{contentType}`                | [przełącza escapowanie i wysyła nagłówek HTTP |#contentType]
| `{debugbreak}`                 | [umieszcza breakpoint w kodzie |#debugbreak]
| `{do}`                         | [wykonuje kod, ale nic nie wyświetla |#do]
| `{dump}`                       | [zrzuca zmienne do Tracy Bar |#dump]
| `{php}`                        | [wykonuje dowolny kod PHP |#php]
| `{spaceless}` … `{/spaceless}` | [usuwa zbędne spacje |#spaceless]
| `{syntax}`                     | [zmiana składni w locie |#syntax]
| `{trace}`                      | [wyświetla ślad stosu |#trace]

.[table-latte-tags language-latte]
|## Pomocnicy kodera HTML
| `n:class`                      | [dynamiczny zapis atrybutu HTML class |#n:class]
| `n:attr`                       | [dynamiczny zapis dowolnych atrybutów HTML |#n:attr]
| `n:tag`                        | [dynamiczny zapis nazwy elementu HTML |#n:tag]
| `n:ifcontent`                  | [pomija pusty znacznik HTML |#n:ifcontent]

.[table-latte-tags language-latte]
|## Dostępne tylko w Nette Framework
| `n:href`                       | [link używany w elementach HTML `<a>` |application:creating-links#W szablonie presentera]
| `{link}`                       | [wyświetla link |application:creating-links#W szablonie presentera]
| `{plink}`                      | [wyświetla link do presentera |application:creating-links#W szablonie presentera]
| `{control}`                    | [renderuje komponent |application:components#Renderowanie]
| `{snippet}` … `{/snippet}`     | [fragment, który można wysłać AJAXem |application:ajax#Snippety w Latte]
| `{snippetArea}`                | [opakowanie dla fragmentów |application:ajax#Obszary snippetów]
| `{cache}` … `{/cache}`         | [buforuje część szablonu |caching:#Buforowanie w Latte]

.[table-latte-tags language-latte]
|## Dostępne tylko z Nette Forms
| `{form}` … `{/form}`           | [renderuje znaczniki formularza |forms:rendering#form]
| `{label}` … `{/label}`         | [renderuje etykietę elementu formularza |forms:rendering#label input]
| `{input}`                      | [renderuje element formularza |forms:rendering#label input]
| `{inputError}`                 | [wyświetla komunikat błędu elementu formularza |forms:rendering#inputError]
| `n:name`                       | [ożywia element formularza |forms:rendering#n:name]
| `{formContainer}` … `{/formContainer}` | [rysowanie kontenera formularza |forms:rendering#Przypadki specjalne]

.[table-latte-tags language-latte]
|## Dostępne tylko z zasobami Nette
| `{asset}` | [renderuje zasób jako element HTML lub URL |assets:#asset]
| `{preload}` | [generuje wskazówki przed załadowaniem dla optymalizacji wydajności |assets:#preload]
| `n:asset` | [dodaje atrybuty zasobów do elementów HTML |assets:#n:asset]


Wyświetlanie
============


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

W Latte używa się znacznika `{=...}` do wyświetlania dowolnego wyrażenia na wyjściu. Latte dba o Twoją wygodę, więc jeśli wyrażenie zaczyna się od zmiennej lub wywołania funkcji, nie trzeba pisać znaku równości. Co w praktyce oznacza, że prawie nigdy nie trzeba go pisać:

```latte
Imię: {$name} {$surname}<br>
Wiek: {date('Y') - $birth}<br>
```

Jako wyrażenie możesz zapisać cokolwiek, co znasz z PHP. Nie musisz po prostu uczyć się nowego języka. Na przykład:


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

Proszę, nie szukaj w poprzednim przykładzie żadnego sensu, ale gdybyś tam jakiś znalazł, napisz do nas :-)


Escapowanie wyjścia
-------------------

Jakie jest najważniejsze zadanie systemu szablonów? Zapobieganie lukom bezpieczeństwa. I dokładnie to robi Latte zawsze, gdy coś wyświetlasz. Automatycznie to escapuje:

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

Aby być precyzyjnym, Latte używa escapowania kontekstowego, co jest tak ważną i unikalną rzeczą, że poświęciliśmy temu [osobny rozdział |safety-first#Escapowanie kontekstowe].

A co jeśli wyświetlasz zawartość zakodowaną w HTML z zaufanego źródła? Wtedy można łatwo wyłączyć escapowanie:

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

.[warning]
Nieprawidłowe użycie filtra `noescape` może prowadzić do powstania podatności XSS! Nigdy go nie używaj, jeśli nie jesteś **całkowicie pewien**, co robisz, i że wyświetlany ciąg pochodzi z zaufanego źródła.


Wyświetlanie w JavaScript
-------------------------

Dzięki escapowaniu kontekstowemu jest niezwykle łatwo wyświetlać zmienne wewnątrz JavaScriptu, a poprawne escapowanie załatwi Latte.

Zmienna nie musi być tylko ciągiem znaków, obsługiwany jest dowolny typ danych, który następnie zostanie zakodowany jako JSON:

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

Wygeneruje:

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

To jest również powód, dla którego wokół zmiennej **nie pisze się cudzysłowów**: Latte doda je samo dla ciągów znaków. A jeśli chciałbyś wstawić zmienną ciągową do innego ciągu, po prostu je połącz:

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

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

	alert('Hello {$name} !');         // BŁĄD!
</script>
```


Filtry
------

Wyświetlone wyrażenie może być zmodyfikowane [filtrem |syntax#Filtry]. W ten sposób na przykład ciąg znaków przekształcimy na wielkie litery i skrócimy do maksymalnie 30 znaków:

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

Filtry możesz stosować również do częściowych części wyrażenia w ten sposób:

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


Warunki
=======


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

Warunki zachowują się tak samo, jak ich odpowiedniki w PHP. Możesz w nich używać tych samych wyrażeń, jakie znasz z PHP, nie musisz uczyć się nowego języka.

```latte
{if $product->inStock > Stock::Minimum}
	W magazynie
{elseif $product->isOnWay()}
	W drodze
{else}
	Niedostępny
{/if}
```

Jak każdy znacznik parzysty, tak i parę `{if} ... {/if}` można zapisywać również w postaci [n:atrybutu |syntax#n:atrybuty], na przykład:

```latte
<p n:if="$count > 0">W magazynie {$count} sztuk</p>
```

Czy wiesz, że do n:atrybutów możesz dołączyć prefiks `tag-`? Wtedy warunek będzie odnosił się tylko do wyświetlenia znaczników HTML, a zawartość między nimi zostanie wyświetlona zawsze:

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

{* wyświetla 'Hello' gdy $clickable jest fałszywe *}
{* wyświetla '<a href="...">Hello</a>' gdy $clickable jest prawdziwe *}
```

Boskie.


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

Jeśli warunek `{if} ... {/if}` zapiszesz w postaci [n:atrybutu |syntax#n:atrybuty], masz możliwość podania również alternatywnej gałęzi za pomocą `n:else`:

```latte
<strong n:if="$count > 0">W magazynie {$count} sztuk</strong>

<em n:else>niedostępny</em>
```

Atrybut `n:else` można użyć również w parze z [`n:ifset` |#ifset elseifset], [`n:foreach` |#foreach], [`n:try` |#try], [#`n:ifcontent`] i [`n:ifchanged` |#ifchanged].


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

Być może Cię zaskoczy, że wyrażenie w warunku `{if}` można podać również w znaczniku zamykającym. Jest to przydatne w sytuacjach, gdy przy otwieraniu warunku jeszcze nie znamy jego wartości. Nazwijmy to odroczoną decyzją.

Na przykład zaczynamy wyświetlać tabelę z rekordami z bazy danych i dopiero po zakończeniu wyświetlania zdajemy sobie sprawę, że w bazie danych nie było żadnego rekordu. Wtedy umieszczamy warunek w znaczniku końcowym `{/if}` i jeśli nie będzie żadnego rekordu, nic z tego się nie wyświetli:

```latte
{if}
	<h1>Lista wierszy z bazy danych</h1>

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

Sprytne, prawda?

W odroczonym warunku można użyć również `{else}`, ale nie `{elseif}`.


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

.[note]
Zobacz także [`{ifset block}` |template-inheritance#Sprawdzanie istnienia bloków]

Za pomocą warunku `{ifset $var}` sprawdzimy, czy zmienna (lub więcej zmiennych) istnieje i ma wartość inną niż *null*. Właściwie jest to to samo, co `if (isset($var))` w PHP. Jak każdy znacznik parzysty, można go zapisywać również w postaci [n:atrybutu |syntax#n:atrybuty], więc pokażmy to jako przykład:

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


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

`{ifchanged}` sprawdza, czy wartość zmiennej zmieniła się od ostatniej iteracji w pętli (foreach, for lub while).

Jeśli w znaczniku podamy jedną lub więcej zmiennych, będzie sprawdzał, czy któraś z nich się zmieniła, i zgodnie z tym wyświetli zawartość. Na przykład poniższy przykład wyświetli pierwszą literę imienia jako nagłówek za każdym razem, gdy podczas wyświetlania imion zmieni się:

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

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

Jeśli jednak nie podamy żadnego argumentu, będzie sprawdzana renderowana zawartość w porównaniu do jej poprzedniego stanu. Oznacza to, że w poprzednim przykładzie możemy spokojnie pominąć argument w znaczniku. I oczywiście możemy również użyć [n:atrybutu |syntax#n:atrybuty]:

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

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

Wewnątrz `{ifchanged}` można również podać klauzulę `{else}`.


`{switch}` `{case}` `{default}`
-------------------------------
Porównuje wartość z wieloma opcjami. Jest to odpowiednik instrukcji warunkowej `switch`, którą znasz z PHP. Jednak Latte ją ulepsza:

- używa ścisłego porównania (`===`)
- nie potrzebuje `break`

Jest to więc dokładny odpowiednik struktury `match`, która pojawiła się w PHP 8.0.

```latte
{switch $transport}
	{case train}
		Pociągiem
	{case plane}
		Samolotem
	{default}
		Inaczej
{/switch}
```

Klauzula `{case}` może zawierać wiele wartości oddzielonych przecinkami:

```latte
{switch $status}
{case $status::New}<b>nowy element</b>
{case $status::Sold, $status::Unknown}<i>niedostępny</i>
{/switch}
```


Pętle
=====

W Latte znajdziesz wszystkie pętle, które znasz z PHP: foreach, for i while.


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

Pętlę zapisujemy dokładnie tak samo jak w PHP:

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

Ponadto ma kilka sprytnych ulepszeń, o których teraz opowiemy.

Latte na przykład sprawdza, czy utworzone zmienne przypadkowo nie nadpisują zmiennych globalnych o tej samej nazwie. Ratuję to sytuacje, gdy liczysz na to, że w `$lang` jest aktualny język strony, i nie zdajesz sobie sprawy, że `foreach $langs as $lang` Ci tę zmienną nadpisało.

Pętlę foreach można również bardzo elegancko i oszczędnie zapisać za pomocą [n:atrybutu |syntax#n:atrybuty]:

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

Czy wiesz, że do n:atrybutów możesz dołączyć prefiks `inner-`? Wtedy w pętli będzie powtarzane tylko wnętrze elementu:

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

Więc wyświetli się coś takiego:

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


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

Wewnątrz pętli `foreach` można podać klauzulę `{else}`, której zawartość zostanie wyświetlona, jeśli pętla jest pusta:

```latte
<ul>
	{foreach $people as $person}
		<li>{$person->name}</li>
	{else}
		<li><em>Przepraszamy, na tej liście nie ma żadnych użytkowników</em></li>
	{/foreach}
</ul>
```


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

Wewnątrz pętli `foreach` Latte tworzy zmienną `$iterator`, za pomocą której możemy sprawdzać przydatne informacje o trwającej pętli:

- `$iterator->first` - czy to pierwsze przejście przez pętlę?
- `$iterator->last` - czy to ostatnie przejście?
- `$iterator->counter` - które to przejście liczone od jednego?
- `$iterator->counter0` - które to przejście liczone od zera?
- `$iterator->odd` - czy to nieparzyste przejście?
- `$iterator->even` - czy to parzyste przejście?
- `$iterator->parent` - iterator otaczający bieżący
- `$iterator->nextValue` - następny element w pętli
- `$iterator->nextKey` - klucz następnego elementu w pętli


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

Latte jest sprytne i `$iterator->last` działa nie tylko dla tablic, ale również gdy pętla przebiega nad ogólnym iteratorem, gdzie liczba elementów nie jest znana z góry.


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

Te znaczniki można używać wewnątrz pętli `{foreach}`. Zawartość `{first}` zostanie wyrenderowana, jeśli jest to pierwsze przejście. Zawartość `{last}` zostanie wyrenderowana… czy zgadniesz? Tak, jeśli jest to ostatnie przejście. Są to właściwie skróty dla `{if $iterator->first}` i `{if $iterator->last}`.

Znaczniki można również elegancko użyć jako [n:atrybut |syntax#n:atrybuty]:

```latte
{foreach $rows as $row}
	{first}<h1>Lista imion</h1>{/first}

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

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

Zawartość znacznika `{sep}` zostanie wyrenderowana, jeśli przejście nie jest ostatnie, jest więc przydatna do renderowania separatorów, na przykład przecinków między wyświetlanymi elementami:

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

To całkiem praktyczne, prawda?


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

Upraszcza grupowanie danych liniowych podczas iteracji w pętli foreach, wykonując iterację w zagnieżdżonej pętli, dopóki warunek jest spełniony. [Przeczytaj szczegółowy przewodnik|cookbook/grouping].

Może również elegancko zastąpić `{first}` i `{last}` w przykładzie powyżej:

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

Zobacz także filtry [batch |filters#batch] i [group |filters#group].


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

Pętlę zapisujemy dokładnie tak samo jak w PHP:

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

Znacznik można również użyć jako [n:atrybut |syntax#n:atrybuty]:

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


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

Pętlę znów zapisujemy dokładnie tak samo jak w PHP:

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

Lub jako [n:atrybut |syntax#n:atrybuty]:

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

Możliwa jest również wariacja z warunkiem w znaczniku końcowym, która odpowiada w PHP pętli do-while:

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


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

Do sterowania dowolną pętlą można używać znaczników `{continueIf ?}` i `{breakIf ?}`, które przejdą do następnego elementu odpowiednio zakończą pętlę przy spełnieniu warunku:

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


Znacznik `{skipIf}` jest bardzo podobny do `{continueIf}`, ale nie zwiększa licznika `$iterator->counter`, więc jeśli go wyświetlamy i jednocześnie pomijamy niektóre elementy, nie będzie dziur w numeracji. A także klauzula `{else}` zostanie wyrenderowana, jeśli pominiemy wszystkie elementy.

```latte
<ul>
	{foreach $people as $person}
		{skipIf $person->age < 18}
		<li>{$iterator->counter}. {$person->name}</li>
	{else}
		<li><em>Przepraszamy, na tej liście nie ma żadnych dorosłych</em></li>
	{/foreach}
</ul>
```


`{exitIf}` .{data-version:3.0.5}
--------------------------------

Zakończy renderowanie szablonu lub bloku przy spełnieniu warunku (tzw. "early exit").

```latte
{exitIf !$messages}

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


Dołączanie szablonu
===================


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

.[note]
Zobacz także [`{include block}` |template-inheritance#Renderowanie bloków]

Znacznik `{include}` wczytuje i renderuje podany szablon. Jeśli mówilibyśmy w języku naszego ulubionego języka PHP, jest to coś w rodzaju:

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

Dołączone szablony nie mają dostępu do zmiennych aktywnego kontekstu, mają dostęp tylko do zmiennych globalnych.

Zmienne do dołączonego szablonu możesz przekazywać w ten sposób:

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

Nazwa szablonu może być dowolnym wyrażeniem w PHP:

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

Dołączoną zawartość można modyfikować za pomocą [filtrów |syntax#Filtry]. Poniższy przykład usunie cały HTML i zmodyfikuje wielkość liter:

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

Domyślnie [dziedziczenie szablonów|template-inheritance] w tym przypadku w żaden sposób nie figuruje. Chociaż w dołączonym szablonie możemy używać bloków, nie dojdzie do zastąpienia odpowiadających bloków w szablonie, do którego się dołącza. Myśl o dołączonych szablonach jako o oddzielnych, zacienionych częściach stron lub modułów. To zachowanie można zmienić za pomocą modyfikatora `with blocks`:

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

Relacja między nazwą pliku podaną w znaczniku a plikiem na dysku jest kwestią [loadera|loaders].


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

Przy dołączaniu szablonu utworzonego przez użytkownika końcowego powinieneś rozważyć tryb sandbox (więcej informacji w [dokumentacji sandbox |sandbox]):

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


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

.[note]
Zobacz także [`{block name}` |template-inheritance#Bloki]

Bloki bez nazwy służą jako sposób na zastosowanie [filtrów |syntax#Filtry] do części szablonu. Na przykład w ten sposób można zastosować filtr [strip |filters#spaceless], który usunie zbędne spacje:

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


Obsługa wyjątków
================


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

Dzięki temu znacznikowi jest niezwykle łatwo tworzyć solidne szablony.

Jeśli podczas renderowania bloku `{try}` dojdzie do wyjątku, cały blok zostanie odrzucony, a renderowanie będzie kontynuowane po nim:

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

Zawartość w opcjonalnej klauzuli `{else}` zostanie wyrenderowana tylko wtedy, gdy wystąpi wyjątek:

```latte
{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
	{else}
	<p>Przepraszamy, nie udało się załadować tweetów.</p>
{/try}
```

Znacznik można również użyć jako [n:atrybut |syntax#n:atrybuty]:

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

Możliwe jest również zdefiniowanie własnego [niestandardowego handlera wyjątków |develop#Obsługa wyjątków], na przykład w celu logowania.


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

Blok `{try}` można zatrzymać i pominąć również ręcznie za pomocą `{rollback}`. Dzięki temu nie musisz z góry sprawdzać wszystkich danych wejściowych, a dopiero podczas renderowania możesz zdecydować, że obiektu w ogóle nie chcesz renderować:

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


Zmienne
=======


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

Nowe zmienne tworzymy w szablonie znacznikiem `{var}`:

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

{* Deklaracja wielokrotna *}
{var $name = 'John Smith', $age = 27}
```

Znacznik `{default}` działa podobnie, ale tworzy zmienne tylko wtedy, gdy nie istnieją. Jeśli zmienna już istnieje i zawiera wartość `null`, nie zostanie nadpisana:

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

Możesz podawać również [typy zmiennych|type-system]. Na razie są one informacyjne i Latte ich nie kontroluje.

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


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

Tak jak funkcja deklaruje swoje parametry, tak i szablon może na początku zadeklarować swoje zmienne:

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

Zmienne `$a` i `$b` bez podanej wartości domyślnej mają automatycznie wartość domyślną `null`. Zadeklarowane typy są na razie informacyjne i Latte ich nie kontroluje.

Inne zmienne niż zadeklarowane nie są przekazywane do szablonu. Tym różni się od znacznika `{default}`.


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

Przechwytuje wyjście do zmiennej:

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

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

Znacznik można, podobnie jak każdy znacznik parzysty, zapisać również jako [n:atrybut |syntax#n:atrybuty]:

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

Wyjście HTML zostanie zapisane do zmiennej `$var` w postaci obiektu `Latte\Runtime\Html`, aby [nie doszło do niepożądanego escapowania |develop#Wyłączanie automatycznego escapowania zmiennej] przy wyświetlaniu.


Inne
====


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

Znacznikiem określisz, jaki typ zawartości reprezentuje szablon. Możliwości są:

- `html` (typ domyślny)
- `xml`
- `javascript`
- `css`
- `calendar` (iCal)
- `text`

Jego użycie jest ważne, ponieważ ustawia [escapowanie kontekstowe |safety-first#Escapowanie kontekstowe] i tylko tak może escapować poprawnie. Na przykład `{contentType xml}` przełącza do trybu XML, `{contentType text}` całkowicie wyłącza escapowanie.

Jeśli parametrem jest pełnoprawny typ MIME, taki jak na przykład `application/xml`, to dodatkowo wysyła nagłówek HTTP `Content-Type` do przeglądarki:

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


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

Oznacza miejsce, w którym nastąpi zatrzymanie wykonania programu i uruchomienie debuggera, aby programista mógł przeprowadzić inspekcję środowiska wykonawczego i sprawdzić, czy program działa zgodnie z oczekiwaniami. Obsługuje [Xdebug |https://xdebug.org/]. Można dodać warunek, który określa, kiedy program ma zostać zatrzymany.

```latte
{debugbreak}                {* zatrzymuje program *}

{debugbreak $counter == 1}  {* zatrzymuje program przy spełnieniu warunku *}
```


`{do}`
------

Wykonuje kod PHP i nic nie wyświetla. Podobnie jak w przypadku wszystkich innych znaczników, kodem PHP rozumie się jedno wyrażenie, zobacz [ograniczenia PHP |syntax#Ograniczenia PHP w Latte].

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


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

Wyświetla zmienną lub aktualny kontekst.

```latte
{dump $name} {* Wyświetla zmienną $name *}

{dump}       {* Wyświetla wszystkie aktualnie zdefiniowane zmienne *}
```

.[caution]
Wymaga biblioteki [Tracy|tracy:].


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

Umożliwia wykonanie dowolnego kodu PHP. Znacznik należy aktywować za pomocą rozszerzenia [RawPhpExtension |develop#RawPhpExtension].


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

Usuwa zbędne białe znaki z wyjścia. Działa podobnie jak filtr [spaceless |filters#spaceless].

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

Wygeneruje

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

Znacznik można również zapisać jako [n:atrybut |syntax#n:atrybuty].


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

Znaczniki Latte nie muszą być ograniczone tylko do pojedynczych nawiasów klamrowych. Możemy wybrać również inny ogranicznik, i to nawet w locie. Służy do tego `{syntax …}`, gdzie jako parametr można podać:

- double: `{{...}}`
- off: całkowicie wyłącza przetwarzanie znaczników Latte

Z wykorzystaniem n:atrybutów można wyłączyć Latte na przykład tylko dla jednego bloku JavaScriptu:

```latte
<script n:syntax="off">
	var obj = {var: 123}; // to już nie jest tag
</script>
```

Latte można bardzo wygodnie używać również wewnątrz JavaScriptu, wystarczy unikać konstrukcji jak w tym przykładzie, gdy litera następuje bezpośrednio po `{`, zobacz [Latte wewnątrz JavaScriptu lub CSS |recipes#Latte wewnątrz JavaScriptu lub CSS].

Jeśli Latte wyłączysz za pomocą `{syntax off}` (tj. znacznikiem, a nie n:atrybutem), będzie konsekwentnie ignorować wszystkie znaczniki aż do `{/syntax}`


{trace}
-------

Wyrzuca wyjątek `Latte\RuntimeException`, którego ślad stosu jest w duchu szablonów. Zatem zamiast wywołań funkcji i metod zawiera wywołania bloków i dołączania szablonów. Jeśli używasz narzędzia do przejrzystego wyświetlania wyrzuconych wyjątków, takiego jak na przykład [Tracy|tracy:], przejrzyście wyświetli się call stack wraz ze wszystkimi przekazywanymi argumentami.


Pomocnicy kodera HTML
=====================


n:class
-------

Dzięki `n:class` bardzo łatwo wygenerujesz atrybut HTML `class` dokładnie według potrzeb.

Przykład: potrzebuję, aby aktywny element miał klasę `active`:

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

A ponadto, aby pierwszy element miał klasy `first` i `main`:

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

I wszystkie elementy mają mieć klasę `list-item`:

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

Niesamowicie proste, prawda?


n:attr
------

Atrybut `n:attr` potrafi z tą samą elegancją co [#n:class] generować dowolne atrybuty HTML.

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

W zależności od zwróconych wartości wyświetli np.:

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

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

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


n:tag
-----

Atrybut `n:tag` potrafi dynamicznie zmieniać nazwę elementu HTML.

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

Jeśli `$heading === null`, wyświetli się bez zmian tag `<h1>`. W przeciwnym razie zmieni się nazwa elementu na wartość zmiennej, więc dla `$heading === 'h3'` wyświetli się:

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

Ponieważ Latte jest bezpiecznym systemem szablonów, sprawdza, czy nowa nazwa znacznika jest prawidłowa i nie zawiera żadnych niepożądanych lub szkodliwych wartości.


n:ifcontent
-----------

Zapobiega temu, aby wyświetlił się pusty element HTML, tj. element nie zawierający niczego poza spacjami.

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

Wyświetli w zależności od wartości zmiennej `$error`:

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

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


Tłumaczenia
===========

Aby znaczniki do tłumaczenia działały, należy [aktywować translator |develop#TranslatorExtension]. Do tłumaczenia możesz również użyć filtra [`translate` |filters#translate].


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

Tłumaczy wartości na inne języki.

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

Translatorowi można przekazywać również inne parametry:

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


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

Tłumaczy części szablonu:

```latte
<h1>{translate}Zamówienie{/translate}</h1>

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

Znacznik można również zapisać jako [n:atrybut |syntax#n:atrybuty], do tłumaczenia wnętrza elementu:

```latte
<h1 n:translate>Zamówienie</h1>
```

Znaczniki Latte

Przegląd i opis wszystkich znaczników systemu szablonów Latte, które są standardowo dostępne.

Wyświetlanie
{$var}, {...} lub {=...} wyświetla escapowaną zmienną lub wyrażenie
{$var|filter} wyświetla z użyciem filtrów
{l} lub {r} wyświetla znak { lub }
Warunki
{if}{elseif}{else}{/if} warunek if
{ifset}{elseifset}{/ifset} warunek ifset
{ifchanged}{/ifchanged} sprawdza, czy nastąpiła zmiana
{switch} {case} {default} {/switch} warunek switch
n:else alternatywna zawartość dla warunków
Pętle
{foreach}{/foreach} foreach
{for}{/for} for
{while}{/while} while
{continueIf $cond} kontynuuj następną iterację
{skipIf $cond} pomiń iterację
{breakIf $cond} przerwanie pętli
{exitIf $cond} wczesne zakończenie
{first}{/first} czy to pierwsze przejście?
{last}{/last} czy to ostatnie przejście?
{sep}{/sep} czy nastąpi kolejne przejście?
{iterateWhile}{/iterateWhile} ustrukturyzowany foreach
$iterator specjalna zmienna wewnątrz foreach
Dołączanie innych szablonów
{include 'file.latte'} wczytuje szablon z innego pliku
{sandbox 'file.latte'} wczytuje szablon w trybie sandbox
Bloki, layouty, dziedziczenie szablonów
{block} blok anonimowy
{block blockname} definiuje blok
{define blockname} definiuje blok do późniejszego użycia
{include blockname} renderowanie bloku
{include blockname from 'file.latte'} renderuje blok z pliku
{import 'file.latte'} wczytuje bloki z szablonu
{layout 'file.latte'} / {extends} określa plik z layoutem
{embed}{/embed} wczytuje szablon lub blok i pozwala nadpisać bloki
{ifset blockname}{/ifset} warunek, czy blok istnieje
Obsługa wyjątków
{try}{else}{/try} przechwytywanie wyjątków
{rollback} odrzucenie bloku try
Zmienne
{var $foo = value} tworzy zmienną
{default $foo = value} tworzy zmienną, jeśli nie istnieje
{parameters} deklaruje zmienne, typy i wartości domyślne
{capture}{/capture} przechwytuje blok do zmiennej
Typy
{varType} deklaruje typ zmiennej
{varPrint} proponuje typy zmiennych
{templateType} deklaruje typy zmiennych według klasy
{templatePrint} proponuje klasę z typami zmiennych
Tłumaczenia
{_...} wyświetla tłumaczenie
{translate}{/translate} tłumaczy zawartość
Inne
{contentType} przełącza escapowanie i wysyła nagłówek HTTP
{debugbreak} umieszcza breakpoint w kodzie
{do} wykonuje kod, ale nic nie wyświetla
{dump} zrzuca zmienne do Tracy Bar
{php} wykonuje dowolny kod PHP
{spaceless}{/spaceless} usuwa zbędne spacje
{syntax} zmiana składni w locie
{trace} wyświetla ślad stosu
Pomocnicy kodera HTML
n:class dynamiczny zapis atrybutu HTML class
n:attr dynamiczny zapis dowolnych atrybutów HTML
n:tag dynamiczny zapis nazwy elementu HTML
n:ifcontent pomija pusty znacznik HTML
Dostępne tylko w Nette Framework
n:href link używany w elementach HTML <a>
{link} wyświetla link
{plink} wyświetla link do presentera
{control} renderuje komponent
{snippet}{/snippet} fragment, który można wysłać AJAXem
{snippetArea} opakowanie dla fragmentów
{cache}{/cache} buforuje część szablonu
Dostępne tylko z Nette Forms
{form}{/form} renderuje znaczniki formularza
{label}{/label} renderuje etykietę elementu formularza
{input} renderuje element formularza
{inputError} wyświetla komunikat błędu elementu formularza
n:name ożywia element formularza
{formContainer}{/formContainer} rysowanie kontenera formularza
Dostępne tylko z zasobami Nette
{asset} renderuje zasób jako element HTML lub URL
{preload} generuje wskazówki przed załadowaniem dla optymalizacji wydajności
n:asset dodaje atrybuty zasobów do elementów HTML

Wyświetlanie

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

W Latte używa się znacznika {=...} do wyświetlania dowolnego wyrażenia na wyjściu. Latte dba o Twoją wygodę, więc jeśli wyrażenie zaczyna się od zmiennej lub wywołania funkcji, nie trzeba pisać znaku równości. Co w praktyce oznacza, że prawie nigdy nie trzeba go pisać:

Imię: {$name} {$surname}<br>
Wiek: {date('Y') - $birth}<br>

Jako wyrażenie możesz zapisać cokolwiek, co znasz z PHP. Nie musisz po prostu uczyć się nowego języka. Na przykład:

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

Proszę, nie szukaj w poprzednim przykładzie żadnego sensu, ale gdybyś tam jakiś znalazł, napisz do nas :-)

Escapowanie wyjścia

Jakie jest najważniejsze zadanie systemu szablonów? Zapobieganie lukom bezpieczeństwa. I dokładnie to robi Latte zawsze, gdy coś wyświetlasz. Automatycznie to escapuje:

<p>{='one < two'}</p>   {* wyświetla: '<p>one &lt; two</p>' *}

Aby być precyzyjnym, Latte używa escapowania kontekstowego, co jest tak ważną i unikalną rzeczą, że poświęciliśmy temu osobny rozdział.

A co jeśli wyświetlasz zawartość zakodowaną w HTML z zaufanego źródła? Wtedy można łatwo wyłączyć escapowanie:

{$trustedHtmlString|noescape}

Nieprawidłowe użycie filtra noescape może prowadzić do powstania podatności XSS! Nigdy go nie używaj, jeśli nie jesteś całkowicie pewien, co robisz, i że wyświetlany ciąg pochodzi z zaufanego źródła.

Wyświetlanie w JavaScript

Dzięki escapowaniu kontekstowemu jest niezwykle łatwo wyświetlać zmienne wewnątrz JavaScriptu, a poprawne escapowanie załatwi Latte.

Zmienna nie musi być tylko ciągiem znaków, obsługiwany jest dowolny typ danych, który następnie zostanie zakodowany jako JSON:

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

Wygeneruje:

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

To jest również powód, dla którego wokół zmiennej nie pisze się cudzysłowów: Latte doda je samo dla ciągów znaków. A jeśli chciałbyś wstawić zmienną ciągową do innego ciągu, po prostu je połącz:

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

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

	alert('Hello {$name} !');         // BŁĄD!
</script>

Filtry

Wyświetlone wyrażenie może być zmodyfikowane filtrem. W ten sposób na przykład ciąg znaków przekształcimy na wielkie litery i skrócimy do maksymalnie 30 znaków:

{$string|upper|truncate:30}

Filtry możesz stosować również do częściowych części wyrażenia w ten sposób:

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

Warunki

{if} {elseif} {else}

Warunki zachowują się tak samo, jak ich odpowiedniki w PHP. Możesz w nich używać tych samych wyrażeń, jakie znasz z PHP, nie musisz uczyć się nowego języka.

{if $product->inStock > Stock::Minimum}
	W magazynie
{elseif $product->isOnWay()}
	W drodze
{else}
	Niedostępny
{/if}

Jak każdy znacznik parzysty, tak i parę {if} ... {/if} można zapisywać również w postaci n:atrybutu, na przykład:

<p n:if="$count > 0">W magazynie {$count} sztuk</p>

Czy wiesz, że do n:atrybutów możesz dołączyć prefiks tag-? Wtedy warunek będzie odnosił się tylko do wyświetlenia znaczników HTML, a zawartość między nimi zostanie wyświetlona zawsze:

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

{* wyświetla 'Hello' gdy $clickable jest fałszywe *}
{* wyświetla '<a href="...">Hello</a>' gdy $clickable jest prawdziwe *}

Boskie.

n:else

Jeśli warunek {if} ... {/if} zapiszesz w postaci n:atrybutu, masz możliwość podania również alternatywnej gałęzi za pomocą n:else:

<strong n:if="$count > 0">W magazynie {$count} sztuk</strong>

<em n:else>niedostępny</em>

Atrybut n:else można użyć również w parze z n:ifset, n:foreach, n:try, `n:ifcontent` i n:ifchanged.

{/if $cond}

Być może Cię zaskoczy, że wyrażenie w warunku {if} można podać również w znaczniku zamykającym. Jest to przydatne w sytuacjach, gdy przy otwieraniu warunku jeszcze nie znamy jego wartości. Nazwijmy to odroczoną decyzją.

Na przykład zaczynamy wyświetlać tabelę z rekordami z bazy danych i dopiero po zakończeniu wyświetlania zdajemy sobie sprawę, że w bazie danych nie było żadnego rekordu. Wtedy umieszczamy warunek w znaczniku końcowym {/if} i jeśli nie będzie żadnego rekordu, nic z tego się nie wyświetli:

{if}
	<h1>Lista wierszy z bazy danych</h1>

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

Sprytne, prawda?

W odroczonym warunku można użyć również {else}, ale nie {elseif}.

{ifset} {elseifset}

Zobacz także {ifset block}

Za pomocą warunku {ifset $var} sprawdzimy, czy zmienna (lub więcej zmiennych) istnieje i ma wartość inną niż null. Właściwie jest to to samo, co if (isset($var)) w PHP. Jak każdy znacznik parzysty, można go zapisywać również w postaci n:atrybutu, więc pokażmy to jako przykład:

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

{ifchanged}

{ifchanged} sprawdza, czy wartość zmiennej zmieniła się od ostatniej iteracji w pętli (foreach, for lub while).

Jeśli w znaczniku podamy jedną lub więcej zmiennych, będzie sprawdzał, czy któraś z nich się zmieniła, i zgodnie z tym wyświetli zawartość. Na przykład poniższy przykład wyświetli pierwszą literę imienia jako nagłówek za każdym razem, gdy podczas wyświetlania imion zmieni się:

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

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

Jeśli jednak nie podamy żadnego argumentu, będzie sprawdzana renderowana zawartość w porównaniu do jej poprzedniego stanu. Oznacza to, że w poprzednim przykładzie możemy spokojnie pominąć argument w znaczniku. I oczywiście możemy również użyć n:atrybutu:

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

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

Wewnątrz {ifchanged} można również podać klauzulę {else}.

{switch} {case} {default}

Porównuje wartość z wieloma opcjami. Jest to odpowiednik instrukcji warunkowej switch, którą znasz z PHP. Jednak Latte ją ulepsza:

  • używa ścisłego porównania (===)
  • nie potrzebuje break

Jest to więc dokładny odpowiednik struktury match, która pojawiła się w PHP 8.0.

{switch $transport}
	{case train}
		Pociągiem
	{case plane}
		Samolotem
	{default}
		Inaczej
{/switch}

Klauzula {case} może zawierać wiele wartości oddzielonych przecinkami:

{switch $status}
{case $status::New}<b>nowy element</b>
{case $status::Sold, $status::Unknown}<i>niedostępny</i>
{/switch}

Pętle

W Latte znajdziesz wszystkie pętle, które znasz z PHP: foreach, for i while.

{foreach}

Pętlę zapisujemy dokładnie tak samo jak w PHP:

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

Ponadto ma kilka sprytnych ulepszeń, o których teraz opowiemy.

Latte na przykład sprawdza, czy utworzone zmienne przypadkowo nie nadpisują zmiennych globalnych o tej samej nazwie. Ratuję to sytuacje, gdy liczysz na to, że w $lang jest aktualny język strony, i nie zdajesz sobie sprawy, że foreach $langs as $lang Ci tę zmienną nadpisało.

Pętlę foreach można również bardzo elegancko i oszczędnie zapisać za pomocą n:atrybutu:

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

Czy wiesz, że do n:atrybutów możesz dołączyć prefiks inner-? Wtedy w pętli będzie powtarzane tylko wnętrze elementu:

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

Więc wyświetli się coś takiego:

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

{else}

Wewnątrz pętli foreach można podać klauzulę {else}, której zawartość zostanie wyświetlona, jeśli pętla jest pusta:

<ul>
	{foreach $people as $person}
		<li>{$person->name}</li>
	{else}
		<li><em>Przepraszamy, na tej liście nie ma żadnych użytkowników</em></li>
	{/foreach}
</ul>

$iterator

Wewnątrz pętli foreach Latte tworzy zmienną $iterator, za pomocą której możemy sprawdzać przydatne informacje o trwającej pętli:

  • $iterator->first – czy to pierwsze przejście przez pętlę?
  • $iterator->last – czy to ostatnie przejście?
  • $iterator->counter – które to przejście liczone od jednego?
  • $iterator->counter0 – które to przejście liczone od zera?
  • $iterator->odd – czy to nieparzyste przejście?
  • $iterator->even – czy to parzyste przejście?
  • $iterator->parent – iterator otaczający bieżący
  • $iterator->nextValue – następny element w pętli
  • $iterator->nextKey – klucz następnego elementu w pętli
{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}

Latte jest sprytne i $iterator->last działa nie tylko dla tablic, ale również gdy pętla przebiega nad ogólnym iteratorem, gdzie liczba elementów nie jest znana z góry.

{first} {last} {sep}

Te znaczniki można używać wewnątrz pętli {foreach}. Zawartość {first} zostanie wyrenderowana, jeśli jest to pierwsze przejście. Zawartość {last} zostanie wyrenderowana… czy zgadniesz? Tak, jeśli jest to ostatnie przejście. Są to właściwie skróty dla {if $iterator->first} i {if $iterator->last}.

Znaczniki można również elegancko użyć jako n:atrybut:

{foreach $rows as $row}
	{first}<h1>Lista imion</h1>{/first}

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

	<hr n:last>
{/foreach}

Zawartość znacznika {sep} zostanie wyrenderowana, jeśli przejście nie jest ostatnie, jest więc przydatna do renderowania separatorów, na przykład przecinków między wyświetlanymi elementami:

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

To całkiem praktyczne, prawda?

{iterateWhile}

Upraszcza grupowanie danych liniowych podczas iteracji w pętli foreach, wykonując iterację w zagnieżdżonej pętli, dopóki warunek jest spełniony. Przeczytaj szczegółowy przewodnik.

Może również elegancko zastąpić {first} i {last} w przykładzie powyżej:

{foreach $rows as $row}
	<table>

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

	</table>
{/foreach}

Zobacz także filtry batchgroup.

{for}

Pętlę zapisujemy dokładnie tak samo jak w PHP:

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

Znacznik można również użyć jako n:atrybut:

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

{while}

Pętlę znów zapisujemy dokładnie tak samo jak w PHP:

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

Lub jako n:atrybut:

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

Możliwa jest również wariacja z warunkiem w znaczniku końcowym, która odpowiada w PHP pętli do-while:

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

{continueIf} {skipIf} {breakIf}

Do sterowania dowolną pętlą można używać znaczników {continueIf ?} i {breakIf ?}, które przejdą do następnego elementu odpowiednio zakończą pętlę przy spełnieniu warunku:

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

Znacznik {skipIf} jest bardzo podobny do {continueIf}, ale nie zwiększa licznika $iterator->counter, więc jeśli go wyświetlamy i jednocześnie pomijamy niektóre elementy, nie będzie dziur w numeracji. A także klauzula {else} zostanie wyrenderowana, jeśli pominiemy wszystkie elementy.

<ul>
	{foreach $people as $person}
		{skipIf $person->age < 18}
		<li>{$iterator->counter}. {$person->name}</li>
	{else}
		<li><em>Przepraszamy, na tej liście nie ma żadnych dorosłych</em></li>
	{/foreach}
</ul>

{exitIf}

Zakończy renderowanie szablonu lub bloku przy spełnieniu warunku (tzw. „early exit“).

{exitIf !$messages}

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

Dołączanie szablonu

{include 'file.latte'}

Zobacz także {include block}

Znacznik {include} wczytuje i renderuje podany szablon. Jeśli mówilibyśmy w języku naszego ulubionego języka PHP, jest to coś w rodzaju:

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

Dołączone szablony nie mają dostępu do zmiennych aktywnego kontekstu, mają dostęp tylko do zmiennych globalnych.

Zmienne do dołączonego szablonu możesz przekazywać w ten sposób:

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

Nazwa szablonu może być dowolnym wyrażeniem w PHP:

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

Dołączoną zawartość można modyfikować za pomocą filtrów. Poniższy przykład usunie cały HTML i zmodyfikuje wielkość liter:

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

Domyślnie dziedziczenie szablonów w tym przypadku w żaden sposób nie figuruje. Chociaż w dołączonym szablonie możemy używać bloków, nie dojdzie do zastąpienia odpowiadających bloków w szablonie, do którego się dołącza. Myśl o dołączonych szablonach jako o oddzielnych, zacienionych częściach stron lub modułów. To zachowanie można zmienić za pomocą modyfikatora with blocks:

{include 'template.latte' with blocks}

Relacja między nazwą pliku podaną w znaczniku a plikiem na dysku jest kwestią loadera.

{sandbox}

Przy dołączaniu szablonu utworzonego przez użytkownika końcowego powinieneś rozważyć tryb sandbox (więcej informacji w dokumentacji sandbox):

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

{block}

Zobacz także {block name}

Bloki bez nazwy służą jako sposób na zastosowanie filtrów do części szablonu. Na przykład w ten sposób można zastosować filtr strip, który usunie zbędne spacje:

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

Obsługa wyjątków

{try}

Dzięki temu znacznikowi jest niezwykle łatwo tworzyć solidne szablony.

Jeśli podczas renderowania bloku {try} dojdzie do wyjątku, cały blok zostanie odrzucony, a renderowanie będzie kontynuowane po nim:

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

Zawartość w opcjonalnej klauzuli {else} zostanie wyrenderowana tylko wtedy, gdy wystąpi wyjątek:

{try}
	<ul>
		{foreach $twitter->loadTweets() as $tweet}
  			<li>{$tweet->text}</li>
		{/foreach}
	</ul>
	{else}
	<p>Przepraszamy, nie udało się załadować tweetów.</p>
{/try}

Znacznik można również użyć jako n:atrybut:

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

Możliwe jest również zdefiniowanie własnego niestandardowego handlera wyjątków, na przykład w celu logowania.

{rollback}

Blok {try} można zatrzymać i pominąć również ręcznie za pomocą {rollback}. Dzięki temu nie musisz z góry sprawdzać wszystkich danych wejściowych, a dopiero podczas renderowania możesz zdecydować, że obiektu w ogóle nie chcesz renderować:

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

Zmienne

{var} {default}

Nowe zmienne tworzymy w szablonie znacznikiem {var}:

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

{* Deklaracja wielokrotna *}
{var $name = 'John Smith', $age = 27}

Znacznik {default} działa podobnie, ale tworzy zmienne tylko wtedy, gdy nie istnieją. Jeśli zmienna już istnieje i zawiera wartość null, nie zostanie nadpisana:

{default $lang = 'cs'}

Możesz podawać również typy zmiennych. Na razie są one informacyjne i Latte ich nie kontroluje.

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

{parameters}

Tak jak funkcja deklaruje swoje parametry, tak i szablon może na początku zadeklarować swoje zmienne:

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

Zmienne $a i $b bez podanej wartości domyślnej mają automatycznie wartość domyślną null. Zadeklarowane typy są na razie informacyjne i Latte ich nie kontroluje.

Inne zmienne niż zadeklarowane nie są przekazywane do szablonu. Tym różni się od znacznika {default}.

{capture}

Przechwytuje wyjście do zmiennej:

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

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

Znacznik można, podobnie jak każdy znacznik parzysty, zapisać również jako n:atrybut:

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

Wyjście HTML zostanie zapisane do zmiennej $var w postaci obiektu Latte\Runtime\Html, aby nie doszło do niepożądanego escapowania przy wyświetlaniu.

Inne

{contentType}

Znacznikiem określisz, jaki typ zawartości reprezentuje szablon. Możliwości są:

  • html (typ domyślny)
  • xml
  • javascript
  • css
  • calendar (iCal)
  • text

Jego użycie jest ważne, ponieważ ustawia escapowanie kontekstowe i tylko tak może escapować poprawnie. Na przykład {contentType xml} przełącza do trybu XML, {contentType text} całkowicie wyłącza escapowanie.

Jeśli parametrem jest pełnoprawny typ MIME, taki jak na przykład application/xml, to dodatkowo wysyła nagłówek HTTP Content-Type do przeglądarki:

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

{debugbreak}

Oznacza miejsce, w którym nastąpi zatrzymanie wykonania programu i uruchomienie debuggera, aby programista mógł przeprowadzić inspekcję środowiska wykonawczego i sprawdzić, czy program działa zgodnie z oczekiwaniami. Obsługuje Xdebug. Można dodać warunek, który określa, kiedy program ma zostać zatrzymany.

{debugbreak}                {* zatrzymuje program *}

{debugbreak $counter == 1}  {* zatrzymuje program przy spełnieniu warunku *}

{do}

Wykonuje kod PHP i nic nie wyświetla. Podobnie jak w przypadku wszystkich innych znaczników, kodem PHP rozumie się jedno wyrażenie, zobacz ograniczenia PHP.

{do $num++}

{dump}

Wyświetla zmienną lub aktualny kontekst.

{dump $name} {* Wyświetla zmienną $name *}

{dump}       {* Wyświetla wszystkie aktualnie zdefiniowane zmienne *}

Wymaga biblioteki Tracy.

{php}

Umożliwia wykonanie dowolnego kodu PHP. Znacznik należy aktywować za pomocą rozszerzenia RawPhpExtension.

{spaceless}

Usuwa zbędne białe znaki z wyjścia. Działa podobnie jak filtr spaceless.

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

Wygeneruje

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

Znacznik można również zapisać jako n:atrybut.

{syntax}

Znaczniki Latte nie muszą być ograniczone tylko do pojedynczych nawiasów klamrowych. Możemy wybrać również inny ogranicznik, i to nawet w locie. Służy do tego {syntax …}, gdzie jako parametr można podać:

  • double: {{...}}
  • off: całkowicie wyłącza przetwarzanie znaczników Latte

Z wykorzystaniem n:atrybutów można wyłączyć Latte na przykład tylko dla jednego bloku JavaScriptu:

<script n:syntax="off">
	var obj = {var: 123}; // to już nie jest tag
</script>

Latte można bardzo wygodnie używać również wewnątrz JavaScriptu, wystarczy unikać konstrukcji jak w tym przykładzie, gdy litera następuje bezpośrednio po {, zobacz Latte wewnątrz JavaScriptu lub CSS.

Jeśli Latte wyłączysz za pomocą {syntax off} (tj. znacznikiem, a nie n:atrybutem), będzie konsekwentnie ignorować wszystkie znaczniki aż do {/syntax}

{trace}

Wyrzuca wyjątek Latte\RuntimeException, którego ślad stosu jest w duchu szablonów. Zatem zamiast wywołań funkcji i metod zawiera wywołania bloków i dołączania szablonów. Jeśli używasz narzędzia do przejrzystego wyświetlania wyrzuconych wyjątków, takiego jak na przykład Tracy, przejrzyście wyświetli się call stack wraz ze wszystkimi przekazywanymi argumentami.

Pomocnicy kodera HTML

n:class

Dzięki n:class bardzo łatwo wygenerujesz atrybut HTML class dokładnie według potrzeb.

Przykład: potrzebuję, aby aktywny element miał klasę active:

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

A ponadto, aby pierwszy element miał klasy first i main:

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

I wszystkie elementy mają mieć klasę list-item:

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

Niesamowicie proste, prawda?

n:attr

Atrybut n:attr potrafi z tą samą elegancją co class generować dowolne atrybuty HTML.

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

W zależności od zwróconych wartości wyświetli np.:

<input type="checkbox">

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

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

n:tag

Atrybut n:tag potrafi dynamicznie zmieniać nazwę elementu HTML.

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

Jeśli $heading === null, wyświetli się bez zmian tag <h1>. W przeciwnym razie zmieni się nazwa elementu na wartość zmiennej, więc dla $heading === 'h3' wyświetli się:

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

Ponieważ Latte jest bezpiecznym systemem szablonów, sprawdza, czy nowa nazwa znacznika jest prawidłowa i nie zawiera żadnych niepożądanych lub szkodliwych wartości.

n:ifcontent

Zapobiega temu, aby wyświetlił się pusty element HTML, tj. element nie zawierający niczego poza spacjami.

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

Wyświetli w zależności od wartości zmiennej $error:

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

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

Tłumaczenia

Aby znaczniki do tłumaczenia działały, należy aktywować translator. Do tłumaczenia możesz również użyć filtra translate.

{_...}

Tłumaczy wartości na inne języki.

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

Translatorowi można przekazywać również inne parametry:

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

{translate}

Tłumaczy części szablonu:

<h1>{translate}Zamówienie{/translate}</h1>

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

Znacznik można również zapisać jako n:atrybut, do tłumaczenia wnętrza elementu:

<h1 n:translate>Zamówienie</h1>