Nette Documentation Preview

syntax
Tagi Latte
**********

.[perex]
Przegląd i opis wszystkich tagów dostępnych domyślnie w systemie szablonów Latte.

.[table-latte-tags language-latte]
|## Wypisywanie
| `{$var}`, `{...}` albo `{=...}` | [wypisuje zescapowaną zmienną lub wyrażenie |#Wypisywanie]
| `{$var\|filter}`               | [wypisuje z zastosowanymi filtrami |#Filtry]
| `{l}` albo `{r}`               | wypisuje znak `{` albo `}`

.[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 wartość się zmieniła |#{ifchanged}]
| `{switch}` `{case}` `{default}` `{/switch}` | [warunek switch |#{switch} {case} {default}]
| `n:else`, `n:elseif`                        | [alternatywna treść dla warunków |#n:else]

.[table-latte-tags language-latte]
|## Pętle
| `{foreach}` … `{/foreach}`     | [#{foreach}]
| `{for}` … `{/for}`             | [#{for}]
| `{while}` … `{/while}`         | [#{while}]
| `{continueIf $cond}`           | [przejście do następnej iteracji |#{continueIf} {skipIf} {breakIf}]
| `{skipIf $cond}`               | [pominięcie bieżącej iteracji pętli |#{continueIf} {skipIf} {breakIf}]
| `{breakIf $cond}`              | [przerwanie pętli |#{continueIf} {skipIf} {breakIf}]
| `{exitIf $cond}`               | [wcześniejsze zakończenie |#{exitIf}]
| `{first}` … `{/first}`         | [czy to pierwsza iteracja? |#{first} {last} {sep}]
| `{last}` … `{/last}`           | [czy to ostatnia iteracja? |#{first} {last} {sep}]
| `{sep}` … `{/sep}`             | [czy nastąpi kolejna iteracja? |#{first} {last} {sep}]
| `{iterateWhile}` … `{/iterateWhile}` | [strukturyzowany foreach |#{iterateWhile}]
| `$iterator`                    | [specjalna zmienna wewnątrz pętli foreach |#$iterator]

.[table-latte-tags language-latte]
|## Dołączanie innych szablonów
| `{include 'file.latte'}`       | [dołącza szablon z innego pliku |#include]
| `{sandbox 'file.latte'}`       | [dołącza 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]
| `{include blockname}`          | [renderuje blok |template-inheritance#Renderowanie bloków]
| `{include blockname from 'file.latte'}` | [renderuje blok z pliku |template-inheritance#Renderowanie bloków]
| `{import 'file.latte'}`        | [importuje bloki z szablonu |template-inheritance#Poziome wykorzystanie]
| `{layout 'file.latte'}` / `{extends}` | [wskazuje plik layoutu |template-inheritance#Dziedziczenie layoutu]
| `{embed}` … `{/embed}`         | [osadza szablon lub blok i pozwala nadpisywać bloki |template-inheritance#Dziedziczenie jednostkowe]
| `{ifset blockname}` … `{/ifset}`   | [warunek sprawdzający istnienie bloku |template-inheritance#Sprawdzanie istnienia bloku]

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

.[table-latte-tags language-latte]
|## Zmienne
| `{var $foo = value}`           | [tworzenie zmiennej |#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 wynik 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 na podstawie klasy |type-system#{templateType}]
| `{templatePrint}`              | [proponuje klasę z typami zmiennych |type-system#{templatePrint}]

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

.[table-latte-tags language-latte]
|## Pozostałe
| `{contentType}`                | [przełącza escapowanie i wysyła nagłówek HTTP |#{contentType}]
| `{debugbreak}`                 | [umieszcza w kodzie breakpoint |#{debugbreak}]
| `{do}`                         | [wykonuje kod, nic nie wypisując |#{do}]
| `{dump}`                       | [zrzuca zmienne do paska Tracy |#{dump}]
| `{php}`                        | [wykonuje dowolny kod PHP |#{php}]
| `{spaceless}` … `{/spaceless}` | [usuwa zbędne białe znaki |#{spaceless}]
| `{syntax}`                     | [zmienia składnię w czasie działania |#{syntax}]
| `{trace}`                      | [wyświetla stack trace |#{trace}]

.[table-latte-tags language-latte]
|## Pomocnicy kodera HTML
| `n:class`                      | [dynamiczny atrybut HTML class |#n:class]
| `n:attr`                       | [dynamiczne atrybuty HTML |#n:attr]
| `n:tag`                        | [dynamiczna nazwa elementu HTML |#n:tag]
| `n:ifcontent`                  | [pomija pusty tag HTML |#n:ifcontent]

.[table-latte-tags language-latte]
|## Dostępne tylko w Nette Framework
| `n:href`                       | [odnośnik używany w elementach HTML `<a>` |application:creating-links#W szablonie presentera]
| `{link}`                       | [wypisuje odnośnik |application:creating-links#W szablonie presentera]
| `{plink}`                      | [wypisuje odnośnik do presentera |application:creating-links#W szablonie presentera]
| `{linkBase}`                   | [zmiana bazy odnośników |application:creating-links#Zmiana bazy odnośników]
| `{control}`                    | [renderuje komponent |application:components#Renderowanie]
| `{snippet}` … `{/snippet}`     | [snippet szablonu, który można wysłać przez AJAX |application:ajax#Snippety w Latte]
| `{snippetArea}`                | [obudowanie snippetu |application:ajax#Obszary snippetów]
| `{cache}` … `{/cache}`         | [cachuje część szablonu |caching:#Buforowanie w Latte]

.[table-latte-tags language-latte]
|## Dostępne tylko z Nette Forms
| `{form}` … `{/form}`           | [renderuje tagi formularza |forms:rendering#{form}]
| `{form scope}`, `{form detached}` | [warianty formularza bez tagu albo odłączony |forms:rendering#{form}]
| `{label}` … `{/label}`         | [renderuje etykietę elementu formularza |forms:rendering#{label} {input}]
| `{input}`                      | [renderuje element formularza |forms:rendering#{label} {input}]
| `{inputError}`                 | [wypisuje komunikat o błędzie elementu formularza |forms:rendering#{inputError}]
| `n:name`                       | [aktywuje element formularza |forms:rendering#n:name]
| `{formContainer}` … `{/formContainer}` | [renderuje kontener formularza |forms:rendering#Przypadki szczególne]

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


Wypisywanie
===========


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

W Latte tag `{=...}` służy do wypisania na wyjście dowolnego wyrażenia. Latte dba o Twoją wygodę, więc jeśli wyrażenie zaczyna się od zmiennej albo wywołania funkcji, nie trzeba pisać znaku równości. W praktyce oznacza to, że prawie nigdy nie trzeba go pisać:

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

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


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

Nie szukaj w poprzednim przykładzie żadnego sensu, ale jeśli go znajdziesz, daj nam znać :-)


Escapowanie wyniku
------------------

Jakie jest najważniejsze zadanie systemu szablonów? Zapobiegać podatnościom bezpieczeństwa. I dokładnie to robi Latte za każdym razem, gdy coś wypisujesz. Automatycznie to escapuje:

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

Ściśle rzecz biorąc, Latte używa escapowania świadomego kontekstu, które jest funkcją tak ważną i unikalną, że poświęciliśmy jej [osobny rozdział |safety-first#Escapowanie świadome kontekstu].

A co, jeśli wypisujesz treść zakodowaną w HTML pochodzącą z zaufanego źródła? Wtedy możesz łatwo wyłączyć escapowanie:

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

.[warning]
Niewłaściwe użycie filtra `noescape` może prowadzić do podatności XSS! Nigdy go nie używaj, o ile nie masz **absolutnej pewności**, co robisz i że wypisywany łańcuch pochodzi z zaufanego źródła.


Wypisywanie w JavaScripcie
--------------------------

Dzięki escapowaniu świadomemu kontekstu wypisywanie zmiennych wewnątrz JavaScriptu jest cudownie łatwe, a Latte zadba o poprawne escapowanie.

Zmienna nie musi być łańcuchem, obsługiwany jest dowolny typ danych, który następnie zostaje zakodowany jako JSON:

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

Wygeneruje:

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

Właśnie dlatego **nie powinieneś pisać cudzysłowów** wokół zmiennej: Latte dodaje je dla łańcuchów automatycznie. A jeśli chcesz wstawić zmienną łańcuchową do innego łańcucha, po prostu je połącz:

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

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

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


Filtry
------

Wypisywane wyrażenie można modyfikować [filtrami |syntax#Filtry]. Ten przykład zamienia łańcuch na wielkie litery i skraca go do maksymalnie 30 znaków:

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

Filtry możesz zastosować także do części wyrażenia, o tak:

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


Warunki
=======


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

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

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

Jak każdy tag parzysty, parę `{if} ... {/if}` można zapisać także [n:atrybutem |syntax#n:atrybuty], na przykład:

```latte
<p n:if="$count > 0">Na stanie {$count} szt.</p>
```

Wiesz, że do n:atrybutów możesz dodać prefiks `tag-`? Wtedy warunek wpłynie tylko na wypisanie tagów HTML, a treść między nimi zostanie wypisana zawsze:

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

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

Świetne.


`n:else` `n:elseif` .{toc: n:else}{data-version:3.0.12}
-------------------------------------------------------

Jeśli zapiszesz warunek `{if} ... {/if}` w postaci [n:atrybutu |syntax#n:atrybuty], masz możliwość podania alternatywnych gałęzi za pomocą `n:else` (od 3.0.12) i `n:elseif` (od 3.1):

```latte
<strong n:if="$count > 0">Na stanie {$count} szt.</strong>

<em n:elseif="$count < 0">Nieprawidłowa liczba</em>

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

Atrybutu `n:else` można używać także w połączeniu z [`n:ifset` |#{ifset} {elseifset}], [`n:foreach` |#{foreach}], [`n:try` |#{try}], [`n:ifcontent`|#n:ifcontent] i [`n:ifchanged` |#{ifchanged}].


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

Może Cię zaskoczyć, że wyrażenie warunku `{if}` można podać także w tagu zamykającym. Przydaje się to w sytuacjach, gdy w chwili otwierania warunku nie znamy jeszcze jego wartości. Nazwijmy to decyzją odroczoną.

Na przykład zaczynamy wypisywać tabelę z rekordami z bazy danych i dopiero po zakończeniu wypisywania orientujemy się, że w bazie nie było żadnych rekordów. Umieszczamy więc warunek w tagu zamykającym `{/if}` i jeśli rekordów nie ma, nic z tego się nie wypisze:

```latte
{if}
	<h1>Lista rekordów z bazy danych</h1>

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

Poręczne, prawda?

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


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

.[note]
Zobacz też [`{ifset block}` |template-inheritance#Sprawdzanie istnienia bloku]

Warunku `{ifset $var}` używa się do ustalenia, czy zmienna (albo kilka zmiennych) istnieje i ma wartość różną od null. To właściwie to samo co `if (isset($var))` w PHP. Jak każdy tag parzysty można go zapisać także [n:atrybutem |syntax#n:atrybuty], pokażmy więc 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 albo while).

Jeśli podamy w tagu jedną lub więcej zmiennych, sprawdzi, czy któraś z nich się zmieniła, i odpowiednio wypisze treść. Na przykład poniższy przykład przy wypisywaniu imion wypisuje jako nagłówek pierwszą literę imienia za każdym razem, gdy się ona zmieni:

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

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

Jeśli jednak nie podamy argumentu, sprawdzana będzie sama wyrenderowana treść w porównaniu z jej poprzednim stanem. Oznacza to, że w poprzednim przykładzie możemy bezpiecznie pominąć argument w tagu. I oczywiście możemy użyć też [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 użyć również klauzuli `{else}`.


`{switch}` `{case}` `{default}`
-------------------------------
Porównuje wartość z wieloma opcjami. Przypomina to instrukcję `switch` znaną z PHP. Latte jednak ją ulepsza:

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

Blisko więc odzwierciedla konstrukcję `match` wprowadzoną w PHP 8.0.

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

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

```latte
{switch $status}
{case $status::New}<b>nowy artykuł</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ę zapisujesz dokładnie tak samo jak w PHP:

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

Ma poza tym kilka poręcznych możliwości, o których teraz opowiemy.

Na przykład Latte sprawdza, czy tworzone zmienne przypadkiem nie nadpisują globalnych zmiennych o tej samej nazwie. Ratuje Cię to przed sytuacjami, w których oczekujesz, że `$lang` zawiera bieżący język strony, i nie zdajesz sobie sprawy, że `foreach $langs as $lang` tę zmienną nadpisał.

Pętlę foreach można też zapisać bardzo elegancko i oszczędnie [n:atrybutem |syntax#n:atrybuty]:

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

Wiesz, że do n:atrybutów możesz dodać prefiks `inner-`? Wtedy w pętli powtórzy się tylko wnętrze elementu:

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

Wypisze więc coś w rodzaju:

```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żesz podać klauzulę `{else}`, której treść wyświetli się, gdy pętla będzie pusta:

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


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

Wewnątrz pętli `foreach` Latte tworzy zmienną `$iterator`, która pozwala poznać przydatne informacje o trwającej pętli:

- `$iterator->first` - czy to pierwsza iteracja?
- `$iterator->last` - czy to ostatnia iteracja?
- `$iterator->counter` - licznik iteracji, licząc od jedynki
- `$iterator->counter0` - licznik iteracji, licząc od zera
- `$iterator->odd` - czy to nieparzysta iteracja?
- `$iterator->even` - czy to parzysta iteracja?
- `$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 też wtedy, gdy pętla przebiega po ogólnym iteratorze, w którym liczba elementów nie jest znana z góry.


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

Tych tagów można używać wewnątrz pętli `{foreach}`. Treść `{first}` renderuje się, jeśli to pierwsza iteracja. Treść `{last}` renderuje się... zgadniesz? Tak, jeśli to ostatnia iteracja. To właściwie skróty dla `{if $iterator->first}` i `{if $iterator->last}`.

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

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

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

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

Treść tagu `{sep}` renderuje się, jeśli iteracja nie jest ostatnia, co czyni go odpowiednim do renderowania separatorów, na przykład przecinków między wypisywanymi elementami:

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

Całkiem praktyczne, prawda?


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

Upraszcza grupowanie danych liniowych przy iteracji w pętli foreach, wykonując iterację w zagnieżdżonej pętli tak długo, jak spełniony jest warunek. [Przeczytaj szczegółową instrukcję|cookbook/grouping].

Może też elegancko zastąpić `{first}` i `{last}` w powyższym przykładzie:

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

Tag można zapisać także jako [n:atrybut |syntax#n:atrybuty]:

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


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

Znów zapisujemy pętlę dokładnie tak samo jak w PHP:

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

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

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

Możliwy jest też wariant z warunkiem w tagu zamykającym, odpowiadający pętli do-while w PHP:

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


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

Do sterowania dowolną pętlą można użyć specjalnych tagów `{continueIf ?}` i `{breakIf ?}`. Przeskakują odpowiednio do następnej iteracji albo kończą pętlę, jeśli warunek jest spełniony:

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


Tag `{skipIf}` jest bardzo podobny do `{continueIf}`, ale nie zwiększa `$iterator->counter`. Zapobiega to lukom w numeracji, gdy wypisujesz licznik i pomijasz część elementów. Ponadto klauzula `{else}` wyrenderuje się, jeśli wszystkie elementy zostaną pominięte.

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


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

Kończy renderowanie szablonu albo bloku, gdy spełniony jest warunek (czyli "early exit").

```latte
{exitIf !$messages}

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


Dołączanie szablonów
====================


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

.[note]
Zobacz też [`{include block}` |template-inheritance#Renderowanie bloków] i [`{embed}` |template-inheritance#Dziedziczenie jednostkowe]

Tag `{include}` wczytuje i renderuje podany szablon. W naszym ulubionym języku PHP to coś w rodzaju:

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

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

Zmienne do dołączanego szablonu możesz przekazać tak:

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

Nazwą szablonu może być dowolne wyrażenie PHP:

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

Czy szablon istnieje, można sprawdzić funkcją [`hasTemplate()` |functions#hasTemplate()].

Dołączaną treść można modyfikować [filtrami |syntax#Filtry]. Poniższy przykład usuwa cały HTML i dostosowuje wielkość liter:

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

Domyślnie [dziedziczenie szablonów|template-inheritance] nie wchodzi tu w grę. Choć w dołączanych szablonach możesz używać bloków, nie zastąpią one odpowiadających im bloków w szablonie, do którego są dołączane. Traktuj dołączane szablony jak niezależne, odizolowane części stron albo modułów. To zachowanie można zmienić modyfikatorem `with blocks`:

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

Związek między nazwą pliku podaną w tagu a plikiem na dysku zależy od [loadera|loaders].


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

Dołączając szablon utworzony przez użytkownika końcowego, powinieneś rozważyć umieszczenie go w sandboxie (więcej informacji w [dokumentacji sandboxa|sandbox]):

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


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

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

Bloki bez nazwy dają możliwość zastosowania [filtrów |syntax#Filtry] do części szablonu. Możesz na przykład zastosować filtr [spaceless |filters#spaceless], aby usunąć zbędne spacje:

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


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


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

Dzięki temu tagowi tworzenie solidnych szablonów jest wyjątkowo łatwe.

Jeśli podczas renderowania bloku `{try}` wystąpi wyjątek, cały blok zostanie odrzucony, a renderowanie będzie kontynuowane za nim:

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

Treść opcjonalnej klauzuli `{else}` renderuje się tylko wtedy, gdy wystąpi wyjątek:

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

Tag można zapisać także jako [n:atrybut |syntax#n:atrybuty]:

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

Można też zdefiniować własny [handler wyjątków |develop#Handler wyjątków], na przykład do celów logowania.


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

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

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


Zmienne
=======


`{var}` `{default}` .{toc: var-default}
---------------------------------------

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

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

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

Tag `{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 = 'en'}
```

Możesz podać także [typy zmiennych|type-system]. Na razie mają charakter informacyjny i Latte ich nie sprawdza.

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


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

Tak jak funkcja deklaruje swoje parametry, 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 mają na razie charakter informacyjny i Latte ich nie sprawdza.

Zmienne inne niż zadeklarowane nie są przekazywane do szablonu. Tym różni się to od tagu `{default}`.


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

Przechwytuje wynik do zmiennej:

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

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

Jak każdy tag parzysty, ten tag można zapisać także jako [n:atrybut |syntax#n:atrybuty]:

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

Wynik HTML zapisywany jest do zmiennej `$var` jako obiekt `Latte\Runtime\Html`, aby [zapobiec niepożądanemu escapowaniu |develop#Wyłączenie automatycznego escapowania zmiennej] przy wypisywaniu.


Pozostałe
=========


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

Tym tagiem podajesz, jaki typ treści reprezentuje szablon. Do wyboru są:

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

Jego użycie jest ważne, bo ustawia [escapowanie zależne od kontekstu |safety-first#Escapowanie świadome kontekstu] i dopiero wtedy Latte może escapować poprawnie. Na przykład `{contentType xml}` przełącza w tryb XML, a `{contentType text}` całkowicie wyłącza escapowanie.

Jeśli parametrem jest pełny typ MIME, na przykład `application/xml`, wysyła też do przeglądarki nagłówek 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}`
--------------

Wskazuje miejsce, w którym wykonywanie programu zostanie wstrzymane. Służy do celów debugowania i pozwala programiście zbadać środowisko uruchomieniowe oraz upewnić się, że kod działa zgodnie z oczekiwaniami. Obsługuje [Xdebug |https://xdebug.org/]. Możesz też dodać warunek określający, kiedy program ma się zatrzymać.

```latte
{debugbreak}                {* wstrzymuje program *}

{debugbreak $counter == 1}  {* wstrzymuje program, jeśli warunek jest spełniony *}
```


`{do}`
------

Wykonuje kod PHP i nic nie wypisuje. Jak przy wszystkich innych tagach, przez kod PHP rozumie się pojedyncze wyrażenie, zobacz [Ograniczenia PHP |syntax#Ograniczenia PHP w Latte].

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


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

Zrzuca zmienną albo bieżący kontekst.

```latte
{dump $name} {* zrzuca zmienną $name *}

{dump}       {* zrzuca wszystkie aktualnie zdefiniowane zmienne *}
```

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


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

Domyślnie `{php}` działa jak przestarzały alias dla [`{do}` |#{do}] i oblicza tylko pojedyncze wyrażenie. Aby wykonywać dowolny kod PHP, tag trzeba aktywować rozszerzeniem [RawPhpExtension |develop#RawPhpExtension].


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

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

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

Wygeneruje:

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

Tag można zapisać także jako [n:atrybut |syntax#n:atrybuty].


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

Tagi Latte nie muszą być zamknięte tylko w pojedynczych klamrach. Możesz wybrać inny separator, nawet w czasie działania. Służy do tego `{syntax …}`, gdzie parametrem może być:

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

Za pomocą n:atrybutów możesz 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 da się bardzo wygodnie używać wewnątrz JavaScriptu, wystarczy unikać konstrukcji jak w tym przykładzie, gdzie bezpośrednio po `{` następuje litera, zobacz [Latte wewnątrz JavaScriptu lub CSS |recipes#Latte wewnątrz JavaScriptu lub CSS].

Jeśli wyłączysz Latte przez `{syntax off}` (czyli tagiem, a nie n:atrybutem), będzie ono ściśle ignorować wszystkie tagi aż do `{/syntax}`.


`{trace}`
---------

Zgłasza wyjątek `Latte\RuntimeException`, którego stack trace utrzymany jest w duchu szablonów. Zamiast wywołań funkcji i metod chodzi więc o wywołania bloków i dołączanie szablonów. Jeśli używasz narzędzia do przejrzystego wyświetlania zgłoszonych wyjątków, na przykład [Tracy|tracy:], zobaczysz wyraźnie stos wywołań wraz ze wszystkimi przekazanymi argumentami.


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


`n:class`
---------

.[note]
Od Latte 3.1 standardowy atrybut HTML class zyskał [tę samą funkcjonalność |html-attributes#Klasy]. Nie musisz więc już używać n:class.

Dzięki `n:class` bardzo łatwo wygenerujesz atrybut HTML `class` dokładnie tak, jak potrzebujesz.

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

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

I dalej, potrzebuję, 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}
```

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

Zadziwiająco proste, prawda?


`n:attr`
--------

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

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

W zależności od zwracanych wartości wypisze na przykład:

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

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

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

Możliwości smart atrybutów w Latte 3.1, takie jak pomijanie wartości `null` czy przekazywanie tablic do `class` albo `style`, działają również wewnątrz `n:attr`:

```latte
<div n:attr="class: [a, b], title: $title"></div>
```


`n:tag`
-------

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

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

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

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

Ponieważ Latte jest bezpiecznym systemem szablonów, sprawdza, czy nowa nazwa tagu jest poprawna i nie zawiera niepożądanych ani złośliwych wartości.


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

Zapobiega wypisaniu pustego elementu HTML, czyli elementu zawierającego wyłącznie białe znaki.

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

W zależności od wartości zmiennej `$error` wypisze:

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

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


Tłumaczenie
===========

Aby tagi tłumaczeń działały, trzeba [aktywować translator |develop#TranslatorExtension]. Do tłumaczenia możesz użyć też filtra [`translate` |filters#translate].


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

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

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

Do translatora można przekazać także 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}
```

Tag można zapisać także jako [n:atrybut |syntax#n:atrybuty], aby przetłumaczyć wnętrze elementu:

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

Tagi Latte

Przegląd i opis wszystkich tagów dostępnych domyślnie w systemie szablonów Latte.

Wypisywanie
{$var}, {...} albo {=...} wypisuje zescapowaną zmienną lub wyrażenie
{$var|filter} wypisuje z zastosowanymi filtrami
{l} albo {r} wypisuje znak { albo }
Warunki
{if}{elseif}{else}{/if} warunek if
{ifset}{elseifset}{/ifset} warunek ifset
{ifchanged}{/ifchanged} sprawdza, czy wartość się zmieniła
{switch} {case} {default} {/switch} warunek switch
n:else, n:elseif alternatywna treść dla warunków
Pętle
{foreach}{/foreach} {foreach}
{for}{/for} {for}
{while}{/while} {while}
{continueIf $cond} przejście do następnej iteracji
{skipIf $cond} pominięcie bieżącej iteracji pętli
{breakIf $cond} przerwanie pętli
{exitIf $cond} wcześniejsze zakończenie
{first}{/first} czy to pierwsza iteracja?
{last}{/last} czy to ostatnia iteracja?
{sep}{/sep} czy nastąpi kolejna iteracja?
{iterateWhile}{/iterateWhile} strukturyzowany foreach
$iterator specjalna zmienna wewnątrz pętli foreach
Dołączanie innych szablonów
{include 'file.latte'} dołącza szablon z innego pliku
{sandbox 'file.latte'} dołącza 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} renderuje blok
{include blockname from 'file.latte'} renderuje blok z pliku
{import 'file.latte'} importuje bloki z szablonu
{layout 'file.latte'} / {extends} wskazuje plik layoutu
{embed}{/embed} osadza szablon lub blok i pozwala nadpisywać bloki
{ifset blockname}{/ifset} warunek sprawdzający istnienie bloku
Obsługa wyjątków
{try}{else}{/try} przechwytywanie wyjątków
{rollback} odrzuca blok try
Zmienne
{var $foo = value} tworzenie zmiennej
{default $foo = value} tworzy zmienną, jeśli nie istnieje
{parameters} deklaruje zmienne, typy i wartości domyślne
{capture}{/capture} przechwytuje wynik do zmiennej
Typy
{varType} deklaruje typ zmiennej
{varPrint} proponuje typy zmiennych
{templateType} deklaruje typy zmiennych na podstawie klasy
{templatePrint} proponuje klasę z typami zmiennych
Tłumaczenie
{_...} wypisuje tłumaczenie
{translate}{/translate} tłumaczy treść
Pozostałe
{contentType} przełącza escapowanie i wysyła nagłówek HTTP
{debugbreak} umieszcza w kodzie breakpoint
{do} wykonuje kod, nic nie wypisując
{dump} zrzuca zmienne do paska Tracy
{php} wykonuje dowolny kod PHP
{spaceless}{/spaceless} usuwa zbędne białe znaki
{syntax} zmienia składnię w czasie działania
{trace} wyświetla stack trace
Pomocnicy kodera HTML
n:class dynamiczny atrybut HTML class
n:attr dynamiczne atrybuty HTML
n:tag dynamiczna nazwa elementu HTML
n:ifcontent pomija pusty tag HTML
Dostępne tylko w Nette Framework
n:href odnośnik używany w elementach HTML <a>
{link} wypisuje odnośnik
{plink} wypisuje odnośnik do presentera
{linkBase} zmiana bazy odnośników
{control} renderuje komponent
{snippet}{/snippet} snippet szablonu, który można wysłać przez AJAX
{snippetArea} obudowanie snippetu
{cache}{/cache} cachuje część szablonu
Dostępne tylko z Nette Forms
{form}{/form} renderuje tagi formularza
{form scope}, {form detached} warianty formularza bez tagu albo odłączony
{label}{/label} renderuje etykietę elementu formularza
{input} renderuje element formularza
{inputError} wypisuje komunikat o błędzie elementu formularza
n:name aktywuje element formularza
{formContainer}{/formContainer} renderuje kontener formularza
Dostępne tylko z Nette Assets
{asset} renderuje zasób jako element HTML albo URL
{preload} generuje wskazówki preload dla optymalizacji wydajności
n:asset dodaje atrybuty zasobu do elementów HTML

Wypisywanie

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

W Latte tag {=...} służy do wypisania na wyjście dowolnego wyrażenia. Latte dba o Twoją wygodę, więc jeśli wyrażenie zaczyna się od zmiennej albo wywołania funkcji, nie trzeba pisać znaku równości. W praktyce oznacza to, że prawie nigdy nie trzeba go pisać:

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

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

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

Nie szukaj w poprzednim przykładzie żadnego sensu, ale jeśli go znajdziesz, daj nam znać :-)

Escapowanie wyniku

Jakie jest najważniejsze zadanie systemu szablonów? Zapobiegać podatnościom bezpieczeństwa. I dokładnie to robi Latte za każdym razem, gdy coś wypisujesz. Automatycznie to escapuje:

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

Ściśle rzecz biorąc, Latte używa escapowania świadomego kontekstu, które jest funkcją tak ważną i unikalną, że poświęciliśmy jej osobny rozdział.

A co, jeśli wypisujesz treść zakodowaną w HTML pochodzącą z zaufanego źródła? Wtedy możesz łatwo wyłączyć escapowanie:

{$trustedHtmlString|noescape}

Niewłaściwe użycie filtra noescape może prowadzić do podatności XSS! Nigdy go nie używaj, o ile nie masz absolutnej pewności, co robisz i że wypisywany łańcuch pochodzi z zaufanego źródła.

Wypisywanie w JavaScripcie

Dzięki escapowaniu świadomemu kontekstu wypisywanie zmiennych wewnątrz JavaScriptu jest cudownie łatwe, a Latte zadba o poprawne escapowanie.

Zmienna nie musi być łańcuchem, obsługiwany jest dowolny typ danych, który następnie zostaje zakodowany jako JSON:

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

Wygeneruje:

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

Właśnie dlatego nie powinieneś pisać cudzysłowów wokół zmiennej: Latte dodaje je dla łańcuchów automatycznie. A jeśli chcesz wstawić zmienną łańcuchową do innego łańcucha, po prostu je połącz:

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

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

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

Filtry

Wypisywane wyrażenie można modyfikować filtrami. Ten przykład zamienia łańcuch na wielkie litery i skraca go do maksymalnie 30 znaków:

{$string|upper|truncate:30}

Filtry możesz zastosować także do części wyrażenia, o tak:

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

Warunki

{if} {elseif} {else}

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

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

Jak każdy tag parzysty, parę {if} ... {/if} można zapisać także n:atrybutem, na przykład:

<p n:if="$count > 0">Na stanie {$count} szt.</p>

Wiesz, że do n:atrybutów możesz dodać prefiks tag-? Wtedy warunek wpłynie tylko na wypisanie tagów HTML, a treść między nimi zostanie wypisana zawsze:

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

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

Świetne.

n:else n:elseif

Jeśli zapiszesz warunek {if} ... {/if} w postaci n:atrybutu, masz możliwość podania alternatywnych gałęzi za pomocą n:else (od 3.0.12) i n:elseif (od 3.1):

<strong n:if="$count > 0">Na stanie {$count} szt.</strong>

<em n:elseif="$count < 0">Nieprawidłowa liczba</em>

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

Atrybutu n:else można używać także w połączeniu z n:ifset, n:foreach, n:try, n:ifcontent i n:ifchanged.

{/if $cond}

Może Cię zaskoczyć, że wyrażenie warunku {if} można podać także w tagu zamykającym. Przydaje się to w sytuacjach, gdy w chwili otwierania warunku nie znamy jeszcze jego wartości. Nazwijmy to decyzją odroczoną.

Na przykład zaczynamy wypisywać tabelę z rekordami z bazy danych i dopiero po zakończeniu wypisywania orientujemy się, że w bazie nie było żadnych rekordów. Umieszczamy więc warunek w tagu zamykającym {/if} i jeśli rekordów nie ma, nic z tego się nie wypisze:

{if}
	<h1>Lista rekordów z bazy danych</h1>

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

Poręczne, prawda?

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

{ifset} {elseifset}

Zobacz też {ifset block}

Warunku {ifset $var} używa się do ustalenia, czy zmienna (albo kilka zmiennych) istnieje i ma wartość różną od null. To właściwie to samo co if (isset($var)) w PHP. Jak każdy tag parzysty można go zapisać także n:atrybutem, pokażmy więc 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 albo while).

Jeśli podamy w tagu jedną lub więcej zmiennych, sprawdzi, czy któraś z nich się zmieniła, i odpowiednio wypisze treść. Na przykład poniższy przykład przy wypisywaniu imion wypisuje jako nagłówek pierwszą literę imienia za każdym razem, gdy się ona zmieni:

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

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

Jeśli jednak nie podamy argumentu, sprawdzana będzie sama wyrenderowana treść w porównaniu z jej poprzednim stanem. Oznacza to, że w poprzednim przykładzie możemy bezpiecznie pominąć argument w tagu. I oczywiście możemy użyć też n:atrybutu:

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

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

Wewnątrz {ifchanged} można użyć również klauzuli {else}.

{switch} {case} {default}

Porównuje wartość z wieloma opcjami. Przypomina to instrukcję switch znaną z PHP. Latte jednak ją ulepsza:

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

Blisko więc odzwierciedla konstrukcję match wprowadzoną w PHP 8.0.

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

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

{switch $status}
{case $status::New}<b>nowy artykuł</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ę zapisujesz dokładnie tak samo jak w PHP:

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

Ma poza tym kilka poręcznych możliwości, o których teraz opowiemy.

Na przykład Latte sprawdza, czy tworzone zmienne przypadkiem nie nadpisują globalnych zmiennych o tej samej nazwie. Ratuje Cię to przed sytuacjami, w których oczekujesz, że $lang zawiera bieżący język strony, i nie zdajesz sobie sprawy, że foreach $langs as $lang tę zmienną nadpisał.

Pętlę foreach można też zapisać bardzo elegancko i oszczędnie n:atrybutem:

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

Wiesz, że do n:atrybutów możesz dodać prefiks inner-? Wtedy w pętli powtórzy się tylko wnętrze elementu:

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

Wypisze więc coś w rodzaju:

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

{else}

Wewnątrz pętli foreach możesz podać klauzulę {else}, której treść wyświetli się, gdy pętla będzie pusta:

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

$iterator

Wewnątrz pętli foreach Latte tworzy zmienną $iterator, która pozwala poznać przydatne informacje o trwającej pętli:

  • $iterator->first – czy to pierwsza iteracja?
  • $iterator->last – czy to ostatnia iteracja?
  • $iterator->counter – licznik iteracji, licząc od jedynki
  • $iterator->counter0 – licznik iteracji, licząc od zera
  • $iterator->odd – czy to nieparzysta iteracja?
  • $iterator->even – czy to parzysta iteracja?
  • $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 też wtedy, gdy pętla przebiega po ogólnym iteratorze, w którym liczba elementów nie jest znana z góry.

{first} {last} {sep}

Tych tagów można używać wewnątrz pętli {foreach}. Treść {first} renderuje się, jeśli to pierwsza iteracja. Treść {last} renderuje się… zgadniesz? Tak, jeśli to ostatnia iteracja. To właściwie skróty dla {if $iterator->first} i {if $iterator->last}.

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

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

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

	<hr n:last>
{/foreach}

Treść tagu {sep} renderuje się, jeśli iteracja nie jest ostatnia, co czyni go odpowiednim do renderowania separatorów, na przykład przecinków między wypisywanymi elementami:

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

Całkiem praktyczne, prawda?

{iterateWhile}

Upraszcza grupowanie danych liniowych przy iteracji w pętli foreach, wykonując iterację w zagnieżdżonej pętli tak długo, jak spełniony jest warunek. Przeczytaj szczegółową instrukcję.

Może też elegancko zastąpić {first} i {last} w powyższym przykładzie:

{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 też filtry batchgroup.

{for}

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

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

Tag można zapisać także jako n:atrybut:

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

{while}

Znów zapisujemy pętlę dokładnie tak samo jak w PHP:

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

Albo jako n:atrybut:

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

Możliwy jest też wariant z warunkiem w tagu zamykającym, odpowiadający pętli do-while w PHP:

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

{continueIf} {skipIf} {breakIf}

Do sterowania dowolną pętlą można użyć specjalnych tagów {continueIf ?} i {breakIf ?}. Przeskakują odpowiednio do następnej iteracji albo kończą pętlę, jeśli warunek jest spełniony:

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

Tag {skipIf} jest bardzo podobny do {continueIf}, ale nie zwiększa $iterator->counter. Zapobiega to lukom w numeracji, gdy wypisujesz licznik i pomijasz część elementów. Ponadto klauzula {else} wyrenderuje się, jeśli wszystkie elementy zostaną pominięte.

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

{exitIf}

Kończy renderowanie szablonu albo bloku, gdy spełniony jest warunek (czyli „early exit“).

{exitIf !$messages}

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

Dołączanie szablonów

{include 'file.latte'}

Zobacz też {include block} i {embed}

Tag {include} wczytuje i renderuje podany szablon. W naszym ulubionym języku PHP to coś w rodzaju:

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

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

Zmienne do dołączanego szablonu możesz przekazać tak:

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

Nazwą szablonu może być dowolne wyrażenie PHP:

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

Czy szablon istnieje, można sprawdzić funkcją hasTemplate().

Dołączaną treść można modyfikować filtrami. Poniższy przykład usuwa cały HTML i dostosowuje wielkość liter:

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

Domyślnie dziedziczenie szablonów nie wchodzi tu w grę. Choć w dołączanych szablonach możesz używać bloków, nie zastąpią one odpowiadających im bloków w szablonie, do którego są dołączane. Traktuj dołączane szablony jak niezależne, odizolowane części stron albo modułów. To zachowanie można zmienić modyfikatorem with blocks:

{include 'template.latte' with blocks}

Związek między nazwą pliku podaną w tagu a plikiem na dysku zależy od loadera.

{sandbox}

Dołączając szablon utworzony przez użytkownika końcowego, powinieneś rozważyć umieszczenie go w sandboxie (więcej informacji w dokumentacji sandboxa):

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

{block}

Zobacz też {block name}

Bloki bez nazwy dają możliwość zastosowania filtrów do części szablonu. Możesz na przykład zastosować filtr spaceless, aby usunąć zbędne spacje:

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

Obsługa wyjątków

{try}

Dzięki temu tagowi tworzenie solidnych szablonów jest wyjątkowo łatwe.

Jeśli podczas renderowania bloku {try} wystąpi wyjątek, cały blok zostanie odrzucony, a renderowanie będzie kontynuowane za nim:

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

Treść opcjonalnej klauzuli {else} renderuje się tylko wtedy, gdy wystąpi wyjątek:

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

Tag można zapisać także jako n:atrybut:

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

Można też zdefiniować własny handler wyjątków, na przykład do celów logowania.

{rollback}

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

{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 tagiem {var}:

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

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

Tag {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 = 'en'}

Możesz podać także typy zmiennych. Na razie mają charakter informacyjny i Latte ich nie sprawdza.

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

{parameters}

Tak jak funkcja deklaruje swoje parametry, 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 mają na razie charakter informacyjny i Latte ich nie sprawdza.

Zmienne inne niż zadeklarowane nie są przekazywane do szablonu. Tym różni się to od tagu {default}.

{capture}

Przechwytuje wynik do zmiennej:

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

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

Jak każdy tag parzysty, ten tag można zapisać także jako n:atrybut:

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

Wynik HTML zapisywany jest do zmiennej $var jako obiekt Latte\Runtime\Html, aby zapobiec niepożądanemu escapowaniu przy wypisywaniu.

Pozostałe

{contentType}

Tym tagiem podajesz, jaki typ treści reprezentuje szablon. Do wyboru są:

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

Jego użycie jest ważne, bo ustawia escapowanie zależne od kontekstu i dopiero wtedy Latte może escapować poprawnie. Na przykład {contentType xml} przełącza w tryb XML, a {contentType text} całkowicie wyłącza escapowanie.

Jeśli parametrem jest pełny typ MIME, na przykład application/xml, wysyła też do przeglądarki nagłówek HTTP Content-Type:

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

{debugbreak}

Wskazuje miejsce, w którym wykonywanie programu zostanie wstrzymane. Służy do celów debugowania i pozwala programiście zbadać środowisko uruchomieniowe oraz upewnić się, że kod działa zgodnie z oczekiwaniami. Obsługuje Xdebug. Możesz też dodać warunek określający, kiedy program ma się zatrzymać.

{debugbreak}                {* wstrzymuje program *}

{debugbreak $counter == 1}  {* wstrzymuje program, jeśli warunek jest spełniony *}

{do}

Wykonuje kod PHP i nic nie wypisuje. Jak przy wszystkich innych tagach, przez kod PHP rozumie się pojedyncze wyrażenie, zobacz Ograniczenia PHP.

{do $num++}

{dump}

Zrzuca zmienną albo bieżący kontekst.

{dump $name} {* zrzuca zmienną $name *}

{dump}       {* zrzuca wszystkie aktualnie zdefiniowane zmienne *}

Wymaga biblioteki Tracy.

{php}

Domyślnie {php} działa jak przestarzały alias dla {do} i oblicza tylko pojedyncze wyrażenie. Aby wykonywać dowolny kod PHP, tag trzeba aktywować rozszerzeniem RawPhpExtension.

{spaceless}

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

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

Wygeneruje:

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

Tag można zapisać także jako n:atrybut.

{syntax}

Tagi Latte nie muszą być zamknięte tylko w pojedynczych klamrach. Możesz wybrać inny separator, nawet w czasie działania. Służy do tego {syntax …}, gdzie parametrem może być:

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

Za pomocą n:atrybutów możesz 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 da się bardzo wygodnie używać wewnątrz JavaScriptu, wystarczy unikać konstrukcji jak w tym przykładzie, gdzie bezpośrednio po { następuje litera, zobacz Latte wewnątrz JavaScriptu lub CSS.

Jeśli wyłączysz Latte przez {syntax off} (czyli tagiem, a nie n:atrybutem), będzie ono ściśle ignorować wszystkie tagi aż do {/syntax}.

{trace}

Zgłasza wyjątek Latte\RuntimeException, którego stack trace utrzymany jest w duchu szablonów. Zamiast wywołań funkcji i metod chodzi więc o wywołania bloków i dołączanie szablonów. Jeśli używasz narzędzia do przejrzystego wyświetlania zgłoszonych wyjątków, na przykład Tracy, zobaczysz wyraźnie stos wywołań wraz ze wszystkimi przekazanymi argumentami.

Pomocnicy kodera HTML

n:class

Od Latte 3.1 standardowy atrybut HTML class zyskał tę samą funkcjonalność. Nie musisz więc już używać n:class.

Dzięki n:class bardzo łatwo wygenerujesz atrybut HTML class dokładnie tak, jak potrzebujesz.

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

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

I dalej, potrzebuję, aby pierwszy element miał klasy first i main:

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

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

Zadziwiająco proste, prawda?

n:attr

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

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

W zależności od zwracanych wartości wypisze na przykład:

<input type="checkbox">

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

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

Możliwości smart atrybutów w Latte 3.1, takie jak pomijanie wartości null czy przekazywanie tablic do class albo style, działają również wewnątrz n:attr:

<div n:attr="class: [a, b], title: $title"></div>

n:tag

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

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

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

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

Ponieważ Latte jest bezpiecznym systemem szablonów, sprawdza, czy nowa nazwa tagu jest poprawna i nie zawiera niepożądanych ani złośliwych wartości.

n:ifcontent

Zapobiega wypisaniu pustego elementu HTML, czyli elementu zawierającego wyłącznie białe znaki.

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

W zależności od wartości zmiennej $error wypisze:

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

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

Tłumaczenie

Aby tagi tłumaczeń działały, trzeba aktywować translator. Do tłumaczenia możesz użyć też filtra translate.

{_...}

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

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

Do translatora można przekazać także 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}

Tag można zapisać także jako n:atrybut, aby przetłumaczyć wnętrze elementu:

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