Výchozí Latte makra
Přehled a popis všech maker šablonovacího systému Latte, které jsou vám standardně k dispozici.
Zajímají vás bližší informace o syntaxi Latte nebo o výchozích helperech? Makra najdete v namespace Nette\Latte\Macros.
| Výpis proměnných a výrazů | |
|---|---|
{$variable} |
vypíše escapovanou proměnnou |
{!$variable} |
vypíše proměnnou bez escapování |
{expression} |
vypíše escapovaný výraz |
{!expression} |
vypíše výraz bez escapování |
| Podmínky | |
{if $cond} … {elseif $cond} … {else} … {/if}
podmínka if |
|
{$cond ? $value1 : $value2} |
ternární operátor |
{$cond ? $value} |
zkrácený „ternární“ operátor |
{ifset $var} … {elseifset $var} … {/ifset} podmínka if (isset()) |
|
{ifCurrent $link} … {/ifCurrent} |
speciální případ {if} pro aktivní odkaz |
| Cykly | |
{foreach $arr as $item} … {/foreach} |
cyklus foreach |
{for expr; expr; expr} … {/for} |
cyklus for |
{while expr} … {/while} |
cyklus while |
{continueIf $cond} |
podmíněný skok na další iteraci |
{breakIf $cond} |
podmíněné ukončení cyklu |
{first} … {/first} |
vypsat při prvním průchodu |
{last} … {/last} |
vypsat při posledním průchodu |
{sep} … {/sep} |
separátor |
| Proměnné | |
{var $foo = value} |
vytvoří proměnnou |
{default $foo = value} |
výchozí proměnnou pokud neexistuje |
{capture $var} … {/capture} |
zachytí blok do proměnné |
| Systémové | |
{include 'file.latte'} |
načte šablonu z dalšího souboru |
{cache $key} … {/cache} |
cachuje část šablony |
{? expression} |
vyhodnotí výraz, ale nevypíše |
{* text komentáře *} |
komentář, bude odstraněn |
{syntax mode} … {/syntax} |
změna syntaxe maker za běhu |
{use Class} |
načte nová makra |
{l} nebo {r} |
vypíše znak { nebo } |
{contentType $type} |
přepne escapování a pošle HTTP hlavičku |
{status $code} |
nastaví stavový HTTP kód |
| Pomocí HTML kodéra | |
n:class |
chytrý zápis HTML atributu class |
n:attr |
chytrý zápis jakéhokoliv HTML atributu |
| Překlady | |
{_}Text{/_} |
přeloží text |
{_expression} |
přeloží výraz a vypíše s escapováním |
{!_expression} |
přeloží výraz a vypíše bez escapování |
| Bloky, layouty, dědičnost šablon | |
{block #block} |
definuje a hned vykreslí blok |
{define #block} |
definuje blok pro pozdější použití |
{include #block} |
vloží blok |
{includeblock 'file.latte'} |
načte bloky z externí šablony |
{layout 'file.latte'} |
určuje soubor s layoutem |
{extends 'file.latte'} |
alias pro {layout} |
{ifset #block} … {/ifset} |
podmínka, zda existuje blok |
| Odkazy | |
n:href |
odkaz používaný
v HTML elementech <a> |
{link Presenter:action} |
vygeneruje odkaz |
{plink Presenter:action} |
vygeneruje odkaz na presenter |
| Ovládací prvky a formuláře | |
{control loginForm} |
vykreslí komponentu |
{form formName} … {/form} |
vykreslí značky formuláře |
{label fieldName} … {/label} |
vykreslí popisku formulářového prvku |
{input fieldName} |
vykreslí formulářový prvek |
n:input |
oživí formulářový prvek |
| AJAX | |
{snippet name} … {/snippet} |
výstřižek, který lze odeslat AJAXem |
| Ladění | |
{dump $variable} |
dumpuje proměnné do Debugger Bar |
{debugbreak $cond} |
umístí do kódu breakpoint |
Vypsání proměnné nebo výrazu
{expression}
S escapováním: (eliminuje riziko Cross Site Scripting):
Jméno: {$name} {$surname}<br>
Věk: {date('Y') - $birth}<br>
Bez escapování uvedením vykřičníku:
<div class="article">
{!$content}
{!nl2br($notes)}
</div>
Alternativně lze použit zápis s rovnítkem {=expression} a
{!=expression}.
Díky technologií Context-Aware Escaping je mimo jiné možné nativně používat PHP proměnné uvnitř JavaScriptu:
$template->arr = array(1, 2, 3);
$template->name = 'Jim Beam';
<script type="text/javascript">
var pole = {$arr};
var name = {$name}; // pozor, zapisuje se bez uvozovek!
</script>
Podmínky {if $cond} … {/if},
{ifCurrent $link}, {$cond ? … : …}
Podmínky se chovají stejně, jako jejich protějšky v PHP:
{if $stock}
Skladem
{elseif $onWay}
Na cestě
{else}
Není dostupné
{/if}
Lze použít i makro {ifset}, která kontroluje existenci
proměnné a odpovídá zápisu if (isset($var)). Makro
{ifset} lze také použít pro ověření existence bloků.
Výraz v podmínce {if} lze uvést také v ukončovací
značce, což se hodí v situacích, kdy při otevírání podmínky ještě
jeho výsledek neznáme:
{if}
<h1>Výpis řádků z databáze</h1>
{foreach $database->table as $row} ... {/foreach}
{/if $row}
Blok {if} s podmínkou v ukončovací značce
nepodporuje makro {elseif}. Makro {else}
použít lze.
Značka {ifCurrent destination} pomáhá zjistit, zda-li je cíl odkazu shodný s aktuální stránkou. Pokud odkaz směřuje na stránku, která je zrovna zobrazena, můžeme ho například jinak nastylovat a podobně. Trik je v tom, že při generování odkazu se detekuje, jestli odkaz míří na aktuální stránku. Výsledek pak vrátí $presenter->getCreatedRequest()->hasFlag(‚current‘).
<!-- příklady použití -->
<a href="{link edit, 10}">edituj</a>
<ul class="menu">
<li><a href="{link Default:default}">...</a></li>
<li><a href="{link}">...</a></li>
...
<li {ifCurrent Default:default}class="current"{/ifCurrent}><a href="{link Default:default}">...</a></li>
<!-- rozšíření scope -->
<li {ifCurrent Default:*}class="current"{/ifCurrent}><a href="{link Default:default}">...</a></li>
</ul>
<!-- znegování -->
{ifCurrent Admin:login}{else}<a href="{link Admin:login}">Přihlašte se!</a>{/ifCurrent}
Ternární operátor ?: vypíše první hodnotu, pokud je podmínka splněna. V opačném případě vypíše hodnotu druhou. Lze použít i ve zkrácené podobě, kdy se za chybějící hodnotu doplní NULL – tj. nevypíše se nic.
dostupnost: {$stock ? 'Skladem' : 'Není dostupné'}
zkráceně: {$stock ? 'Skladem'}
Cykly {foreach}, {for},
{while}
Cykly foreach, for a while se chovají
stejně, jako jejich protějšky v PHP.
{foreach $result as $row}
<span>{$row->title}</span>
{/foreach}
{while $row = $result->fetch()}
<span>{$row->title}</span>
{/while}
{for $i = 0; $i < 10; $i++}
<span>Položka {$i}</span>
{/for}
Uvnitř cyklu je inicializovaná proměnná $iterator, díky
které můžeme zjišťovat užitečné informace o probíhajícím cyklu. Její
API disponuje čítačem průchodů a metodami zjišťujícími, zda je
aktuální průchod sudý, lichý, první nebo poslední:
isFirst()– prochází se cyklem poprvé?isLast()– jde o poslední průchod?getCounter()– čítač průchodů cyklem počítaný od jedničkyisOdd()– jde o lichý průchod?isEven()– jde o sudý průchod?
Objekt $iterator má vlastnosti
třídy Nette\Object, proto lze místo $iterator->isFirst()
psát $iterator->first a podobně. Příklad:
{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}
Konstrukci {if $iterator->first}<table>{/if} lze
nahradit za ekvivalentní {first}<table>{/first}, obdobně
podmínku s last lze zapsat jako
{last}</table>{/last}. A nakonec, ekvivalentem {if
!$iterator->last} … {/if} (tj. neposlední prvek) je makro
{sep} … {/sep}. Obvykle jim označíme oddělovač, například
čárku mezi vypisovanými položkami, čímž zajistíme, že se nevypíše
přebývající pravostranná čárka:
{foreach $items as $item} {$item} {sep}, {/sep} {/foreach}
Uvnitř cyklu lze používat makra {continueIf ?} a
{breakIf ?}, které přejdou na další prvek resp. ukončí cyklus
při splnění podmínky:
{foreach $rows as $row}
{continueIf $row->parent == NULL}
...
{/foreach}
Deklarace proměnných {var} a
{default}
Proměnné můžeme deklarovat přímo v šabloně makrem
{var}:
{var $name = 'John Smith'}
{var $age = 27}
{* Vícenásobná deklarace *}
{var $name = 'John Smith', $age = 27}
Makro {default} funguje podobně s tím rozdílem, že
nastavuje hodnoty jen neexistujícím proměnným:
{default $lang = 'cs'}
Zachytávání do proměnné
{capture}
Makrem {capture} lze zachytit výstup do proměnné:
{capture $var}
<ul>
<li>Hello World</li>
</ul>
{/capture}
<p>Captured: {$var}</p>
Pokud chcete zachytit výstup jen proto, abyste na něj mohli aplikovat nějaký helper, je jednodušší helper aplikovat přímo na blok:
{block|strip}
<ul>
<li>Hello World</li>
</ul>
{/block}
Vložení souboru {include}
Do šablony lze vložit jinou šablonu. Vložený soubor má k dispozici globální proměnné aktuální šablony a případné další parametry, které mu při volání předáme:
{include 'basket.latte'}
{include 'menu.latte', level => 3, data => $menu}
Makro {include} se kromě vkládání souborů
používá i pro vkládání bloků.
Vyhodnocení kódu {?
expression}
Vyhodnotí kód a nic nevypisuje.
Hlavička {contentType}
Přepne Context-Aware
Escaping do kontextu určeného argumentem a všechny proměnné se
escapují podle pravidel tohoto kontextu. Například {contentType
xml} přepne do režimu XML, {contentType text} escapování
zcela vypne.
Pokud je parametrem plnohodnotný MIME type, tak se navíc odešle jako HTTP hlavička do prohlížeče:
{contentType application/xml}
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>RSS feed</title>
<item>
...
</item>
</channel>
</rss>
Hlavička {status}
Odešle HTTP stavový kód:
{status 500}
Pokud již nelze hlavičky odeslat, vyhodí výjimku. Té se dá předejít
„volitelným odesláním“ uvedením otazníku za kód {status
500?}.
Změna syntaxe {syntax}
Makra nemusejí být uzavřena výhradně do jednoduchých složených
závorek, můžeme si zvolit i jiný oddělovač a to dokonce za běhu.
Slouží k tomu makro {syntax …}, kde jako parametr
lze uvést:
- latte:
{...} - double:
{{...}} - asp:
<%...%> - python:
{% ... %}a{{ ... }} - off: vypne zpracování maker
S využitím n:maker lze vypnout Latte třeba jen jednomu bloku JavaScriptu:
<script n:syntax="off">
var obj = {var: 123}; // tohle neni makro
</script>
Latte je pohodlně použitelné i v JavaScriptu, jen se stačí vyhnout
konstrukci uvedené v předchozím příkladu. Buď zápisem mezery za
otevírací složenou závorku { var: 123} nebo použitím uvozovek
kolem identifikátoru {'var': 123}.
Pokud Latte vypnete pomocí {syntax off} (tj. makrem syntax,
nikoliv n:makrem), mějte na paměti, že ho již zpátky nemůžete zapnout
pomocí {/syntax}. Žádné složené závorky se nezpracovávají,
tudíž ani tag pro ukončení výjimky v syntaxi.
n:class
Potřebujeme vyřešit běžný úkol: vypisujeme data z databáze jako
elementy <li>, neznáme dopředu jejich počet a chceme, aby
každý lichý řádek měl třídu alt a poslední třídu
last. Pokud by byl poslední řádek lichý, má mít obě třídy.
A protože jsme puntičkáři, nechceme v kódu žádné prázdné
<li class=" "> apod.
Díky makru n:class tohle zapíšeme neskutečně snadno:
<ul>
{foreach $data as $item}
<li n:class="$iterator->odd ? alt, $iterator->last ? last">{$item}</li>
{/foreach}
</ul>
Anebo potřebujete označit aktivní menu třídou current?
<a href="#" n:class="$presenter->isLinkCurrent('Presenter:*') ? current">
Úžasné, že?
n:attr
Makro n:attr umí s elegancí podobnou makru n:class generovat libovolné HTML atributy. Hodí se
především v případech, kdy nevíme, které atributy budeme chtít vypsat a
které ne.
<input type="checkbox" n:attr="value => $value, checked => $checked">
Vypíše v závislosti na hodnotách proměnných $value nebo
$checked:
<input type="checkbox">
{* $value = 'Hello' *}
<input type="checkbox" value="Hello">
{* $checked = TRUE *}
<input type="checkbox" value="Hello" checked>
Překlady {_expression}
Makro usnadňuje automatizované překlady v šablonách. Pro jejich správnou funkčnost musí být nastaven překladač, viz lokalizace:
$template->setTranslator(new MyTranslator);
Poté bude jakýkoliv výraz zapsaný v tomto makru automaticky přeložen:
{_$variable}
Pro textové části šablony lze použít párovou variantu:
{_}Text, který bude přeložen{/_}
Bloky {block} a {define}
Bloky slouží pro označení libovolné oblasti šablony. Třeba proto, abychom na ni aplikovali volání helperu (viz příklad) nebo proto, abychom ji pojmenovali a mohli poté na jiném místě znovu vložit.
{block #sidebar}
<h3>Menu</h3>
...
{/block}
Bloky lze zanořovat do sebe. A pochopitelně je můžeme zapsat prostřednictvím n:makra:
{block #sidebar}
<h3>Menu</h3>
...
<ul n:block="menulist">
...
</ul>
{/block}
Blok se na svém místě vykreslí. Pokud bychom chtěli pojmenovaný blok
jen definovat bez vykreslení, použijeme místo makra {block}
makro {define}.
Název bloku může být také určen proměnnou: {block $var} …
{/block}.
Každý blok vidí proměnné ze svého okolí. Avšak vytvoření nebo změna hodnoty proměnné uvnitř bloku se projeví pouze v něm (a pochopitelně i ve vnořených blocích).
Existenci bloku můžeme ověřit makrem {ifset #sidebar}.
Vkládání bloků {include
#block}
Vložení bloku zajistí makro {include}. Abychom se odlišili
od vkládání souboru, uvedeme před názvem bloku mřížku:
{include #sidebar}
Při vkládání bloku je možné mu předat parametry:
{include #sidebar, id => 123, name => $value}
Můžeme vložit i blok, jehož název je uložen v proměnné:
{include #$block$name}
V bloku lze vložit i sebe sama, což lze použít např. pro vykreslení stromového menu.
{block #menu}
<ul>
{foreach $menu as $item}
<li>{if is_array($item)}
{include #menu, menu => $item}
{else}
{$item}
{/if}</li>
{/foreach}
</ul>
{/block}
Místo {include #menu, ...} lze psát také {include
#this, ...}.
Rozšiřování a dědičnost šablon
{layout}
Rozšiřování šablon (též dědičnost šablon) představuje mocný nástroj, který umožňuje snadnou a efektivní tvorbu i velmi komplikovaných layoutů bez nutnosti zbytečného opakování kódu.
Mějme dvě jednoduché stránky. První:
<html>
<head>
<title>První stránka | Můj web</title>
</head>
<body>
<div id="sidebar">
<ul>...</ul>
</div>
<div id="content">
<p>Lorem Gypsum...</p>
</div>
</body>
</html>
A druhou:
<html>
<head>
<title>Druhá stránka | Můj web</title>
</head>
<body>
<div id="sidebar">
<ul>...</ul>
</div>
<div id="content">
<p>Proin eu sem purus. Donec bibendum
vestibulum...</p>
</div>
</body>
</html>
Stránky se liší pouze elementem <title> a
<div#content>. Vytvoříme si proto layout, ve kterém budou
všechny společné části, a vytvoříme tzv. placeholdery. Což kupodivu
nebude nic jiného, než klasický blok:
Soubor @layout.latte:
<html>
<head>
<title>{block #title}{/block} | Můj web</title>
</head>
<body>
<div id="sidebar">
<ul>...</ul>
</div>
<div id="content">{block #content}{/block}</div>
</body>
</html>
V jednotlivých šablonách se nyní na layout odkážeme makrem
{layout} a můžeme je redukovat na ony dva bloky:
{layout '@layout.latte'}
{block #title}První stránka{/block}
{block #content}<p>Lorem Gypsum...</p>{/block}
Obdobně bude vypadat i stránka druhá.
Nejsme dokonce ani omezeni dvoustupňovým layoutem. Vrstev může být totiž tolik, kolik se nám hodí.
Vykreslování komponent {control
…}
Značka {control} slouží k vykreslování komponent
presenteru. Pro lepší pochopení je dobré vědět, jak se tato značka
přeloží do PHP.
{control cartControl} pro celý košík na stránce
{control cartControl:small} pro malý náhledový košík
se přeloží jako:
$control->getComponent('cartControl')->render();
$control->getComponent('cartControl')->renderSmall();
Metoda getComponent() vrací komponentu cartControl
a nad touto komponentou volá metodu render(), resp.
renderSmall() pokud je jiný způsob renderování uveden ve
značce za dvojtečkou.
Lze použít i volání s parametry, které se předají render metodám, například:
{control cartControl:small, $maxItems}
se přeloží jako:
$control->getComponent('cartControl')->renderSmall($maxItems);
Formuláře {form}, {input},
{label}
Makra usnadňují vykreslení formulářů a jejich prvků:
{form myForm}
<table>
<tr n:foreach="$form->controls as $name => $field">
<th>{label $name /}<th>
<td>{input $name}</td>
</tr>
</table>
{/form}
Makro {input} vykreslí jakýkoliv prvek, včetně select boxů
nebo textarea. Makro {label} může být volitelně párové,
např. {label}Věk{/label}, a ohraničený text bude u vícejazyčných
formulářů také přeložen.
Dumpování proměnných
{dump}
{dump $name} {* Vypíše proměnnou $name *}
{dump} {* Vypíše všechny aktuálně definované proměnné *}
Break point {debugbreak}
Určuje místo, kde dojde k zastavení vykonávání programu. Používá se při ladění, aby mohl programátor provést inspekci běhového prostředí a zjistil, zda program funguje podle očekávání. Podporován je Xdebug a PhpEd. Lze doplnit podmínku, která určuje, kdy má být program zastaven.
{debugbreak} {* Zastaví program *}
{debugbreak $counter == 1} {* Zastaví program při splnění podmínky *}
