Nette Documentation Preview

syntax
Dedovanje predlog in ponovna uporabnost
***************************************

.[perex]
Mehanizmi ponovne uporabnosti in dedovanja predlog povečujejo vašo produktivnost, saj vsaka predloga vsebuje le svojo edinstveno vsebino, ponavljajoči se elementi in strukture pa so ponovno uporabljeni. Predstavljamo tri koncepte: [dedovanje postavitve |#layout inheritance], [horizontalno ponovno uporabo |#horizontal reuse] in [dedovanje enot |#unit inheritance].

Koncept dedovanja predlog Latte je podoben dedovanju razredov PHP. Določite **starševsko predlogo**, ki jo lahko druge **družinske predloge** razširijo in prekrijejo dele starševske predloge. To se odlično obnese, kadar si elementi delijo skupno strukturo. Se vam zdi zapleteno? Brez skrbi, ni.


Dedovanje postavitve `{layout}` .{toc: Layout Inheritance}
==========================================================

Oglejmo si dedovanje predlog postavitve s primerom. To je nadrejena predloga, ki jo bomo na primer poimenovali `layout.latte` in opredeljuje skeletni dokument HTML.

```latte
<!doctype html>
<html lang="en">
<head>
	<title>{block title}{/block}</title>
	<link rel="stylesheet" href="style.css">
</head>
<body>
	<div id="content">
		{block content}{/block}
	</div>
	<div id="footer">
		{block footer}&copy; Copyright 2008{/block}
	</div>
</body>
</html>
```

Oznake `{block}` opredeljujejo tri bloke, ki jih lahko zapolnijo podrejene predloge. Vse, kar naredi oznaka bloka, je, da pove gonilniku predloge, da lahko podrejena predloga prekrije te dele predloge z opredelitvijo lastnega bloka z istim imenom.

Otroška predloga je lahko videti takole:

```latte
{layout 'layout.latte'}

{block title}My amazing blog{/block}

{block content}
	<p>Welcome to my awesome homepage.</p>
{/block}
```

Pri tem je ključna oznaka `{layout}`. Ta sporoča mehanizmu predlog, da ta predloga "razširja" drugo predlogo. Ko Latte upodablja to predlogo, najprej poišče nadrejeno - v tem primeru `layout.latte`.

Takrat bo mehanizem predloge opazil tri blokovne oznake v `layout.latte` in te bloke nadomestil z vsebino podrejene predloge. Upoštevajte, da ker otroška predloga ni opredelila bloka *footer*, se namesto tega uporabi vsebina iz starševske predloge. Vsebina znotraj oznake `{block}` v nadrejeni predlogi se vedno uporabi kot nadomestna možnost.

Rezultat je lahko videti takole:

```latte
<!doctype html>
<html lang="en">
<head>
	<title>My amazing blog</title>
	<link rel="stylesheet" href="style.css">
</head>
<body>
	<div id="content">
		<p>Welcome to my awesome homepage.</p>
	</div>
	<div id="footer">
		&copy; Copyright 2008
	</div>
</body>
</html>
```

V predlogi otroka se bloki lahko nahajajo samo na zgornji ravni ali znotraj drugega bloka, tj:

```latte
{block content}
	<h1>{block title}Welcome to my awesome homepage{/block}</h1>
{/block}
```

Prav tako bo blok vedno ustvarjen ne glede na to, ali je okoliški pogoj `{if}` ovrednoten kot true ali false. V nasprotju s tem, kar morda mislite, ta predloga opredeljuje blok.

```latte
{if false}
	{block head}
		<meta name="robots" content="noindex, follow">
	{/block}
{/if}
```

Če želite, da se izpis znotraj bloka prikaže pogojno, namesto tega uporabite naslednje:

```latte
{block head}
	{if $condition}
		<meta name="robots" content="noindex, follow">
	{/if}
{/block}
```

Podatki zunaj blokov v podrejeni predlogi se izvedejo pred prikazom predloge za postavitev, zato jo lahko uporabite za opredelitev spremenljivk, kot je `{var $foo = bar}`, in širjenje podatkov v celotno dedno verigo:

```latte
{layout 'layout.latte'}
{var $robots = noindex}

...
```


Večnivojsko dedovanje .[#toc-multilevel-inheritance]
----------------------------------------------------
Uporabite lahko toliko ravni dedovanja, kolikor jih potrebujete. Eden od pogostih načinov uporabe dedovanja postavitve je naslednji tristopenjski pristop:

1) Ustvarite predlogo `layout.latte`, ki vsebuje glavni videz vašega spletnega mesta.
2) Ustvarite predlogo `layout-SECTIONNAME.latte` za vsak razdelek svojega spletnega mesta. Na primer `layout-news.latte`, `layout-blog.latte` itd. Vse te predloge razširjajo spletno stran `layout.latte` in vključujejo sloge/oblikovanje, značilne za posamezno poglavje.
3) Ustvarite posamezne predloge za vsako vrsto strani, na primer za novičarski članek ali zapis na blogu. Te predloge razširjajo ustrezno predlogo za razdelek.


Dinamično dedovanje postavitve .[#toc-dynamic-layout-inheritance]
-----------------------------------------------------------------
Kot ime nadrejene predloge lahko uporabite spremenljivko ali kateri koli izraz PHP, zato se lahko dedovanje obnaša dinamično:

```latte
{layout $standalone ? 'minimum.latte' : 'layout.latte'}
```

Uporabite lahko tudi API Latte za [samodejno |develop#automatic-layout-lookup] izbiro predloge za postavitev.


Nasveti .[#toc-tips]
--------------------
Tukaj je nekaj nasvetov za delo z dedovanjem postavitve:

- Če v predlogi uporabite `{layout}`, mora biti to prva oznaka v predlogi.

- Postavitev lahko [iščete samodejno |develop#automatic-layout-lookup] (kot v [predstavitvah |application:templates#Template Lookup]). Če v tem primeru predloga ne sme imeti postavitve, se to označi z oznako `{layout none}`.

- Oznaka `{layout}` ima vzdevek `{extends}`.

- Ime datoteke razširjene predloge je odvisno od programa [za nalaganje predlog |extending-latte#Loaders].

- Na voljo je lahko poljubno število blokov. Ne pozabite, da podrejenim predlogam ni treba opredeliti vseh nadrejenih blokov, zato lahko v več blokov vnesete razumne privzete nastavitve, pozneje pa opredelite le tiste, ki jih potrebujete.


Bloki `{block}` .{toc: Blocks}
==============================

.[note]
Glej tudi anonimni [`{block}` |tags#block]

Blok omogoča spreminjanje načina upodabljanja določenega dela predloge, vendar na noben način ne posega v okoliško logiko. Z naslednjim primerom ponazorimo, kako blok deluje in, kar je še pomembneje, kako ne deluje:

```latte .{file: parent.latte}
{foreach $posts as $post}
{block post}
	<h1>{$post->title}</h1>
	<p>{$post->body}</p>
{/block}
{/foreach}
```

Če to predlogo prikažete, bo rezultat popolnoma enak z oznakami bloka ali brez njih. Bloki imajo dostop do spremenljivk iz zunanjih obsegov. To je le način, da ga lahko podrejena predloga prekrije:

```latte .{file: child.latte}
{layout 'parent.Latte'}

{block post}
	<article>
		<header>{$post->title}</header>
		<section>{$post->text}</section>
	</article>
{/block}
```

Sedaj bo zanka pri upodabljanju podrejene predloge uporabila blok, opredeljen v podrejeni predlogi `child.Latte`, namesto bloka, opredeljenega v osnovni predlogi `parent.Latte`; izvedena predloga je nato enakovredna naslednji:

```latte
{foreach $posts as $post}
	<article>
		<header>{$post->title}</header>
		<section>{$post->text}</section>
	</article>
{/foreach}
```

Če pa znotraj poimenovanega bloka ustvarimo novo spremenljivko ali zamenjamo vrednost obstoječe, bo sprememba vidna samo znotraj bloka:

```latte
{var $foo = 'foo'}
{block post}
	{do $foo = 'new value'}
	{var $bar = 'bar'}
{/block}

foo: {$foo}                  // prints: foo
bar: {$bar ?? 'not defined'} // prints: not defined
```

Vsebino bloka lahko spremenimo s [filtri |syntax#filters]. Naslednji primer odstrani ves HTML in ga naslovi:

```latte
<title>{block title|stripHtml|capitalize}...{/block}</title>
```

Oznaka je lahko zapisana tudi kot [n:attribute |syntax#n:attributes]:

```latte
<article n:block=post>
	...
</article>
```


Lokalni bloki .[#toc-local-blocks]
----------------------------------

Vsak blok prekrije vsebino nadrejenega bloka z istim imenom. Razen lokalnih blokov. Ti so nekaj podobnega kot zasebne metode v razredu. Ustvarite lahko predlogo, ne da bi vas skrbelo, da bi jih - zaradi naključja imen blokov - druga predloga prepisala.

```latte
{block local helper}
	...
{/block}
```


Tiskanje blokov `{include}` .{toc: Printing Blocks}
---------------------------------------------------

.[note]
Glej tudi [`{include file}` |tags#include]

Če želite blok natisniti na določenem mestu, uporabite oznako `{include blockname}`:

```latte
<title>{block title}{/block}</title>

<h1>{include title}</h1>
```

Prikažete lahko tudi blok iz druge predloge:

```latte
{include footer from 'main.latte'}
```

Izpisani blok nima dostopa do spremenljivk aktivnega konteksta, razen če je blok definiran v isti datoteki, v katero je vključen. Imajo pa dostop do globalnih spremenljivk.

Spremenljivke lahko bloku posredujete na naslednji način:

```latte
{include footer, foo: bar, id: 123}
```

Kot ime bloka lahko uporabite spremenljivko ali kateri koli izraz v PHP. V tem primeru pred spremenljivko dodajte ključno besedo `block`, da se ob sestavljanju ve, da gre za blok, in ne za [vstavljanje predloge, |tags#include] katere ime je lahko tudi v spremenljivki:

```latte
{var $name = footer}
{include block $name}
```

Blok se lahko izpiše tudi znotraj samega sebe, kar je uporabno na primer pri upodabljanju drevesne strukture:

```latte
{define menu, $items}
<ul>
	{foreach $items as $item}
		<li>
		{if is_array($item)}
			{include menu, $item}
		{else}
			{$item}
		{/if}
		</li>
	{/foreach}
</ul>
{/define}
```

Namesto `{include menu, ...}` lahko zapišemo tudi `{include this, ...}`, kjer `this` pomeni trenutni blok.

Natisnjeno vsebino lahko spreminjamo s [filtri |syntax#filters]. Naslednji primer odstrani ves HTML in ga označi z naslovi:

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


Nadrejeni blok .[#toc-parent-block]
-----------------------------------

Če morate vsebino bloka izpisati iz nadrejene predloge, bo to storila izjava `{include parent}`. To je uporabno, če želite dodati vsebino nadrejenega bloka, namesto da bi ga v celoti prepisali.

```latte
{block footer}
	{include parent}
	<a href="https://github.com/nette">GitHub</a>
	<a href="https://twitter.com/nettefw">Twitter</a>
{/block}
```


Definicije `{define}` .{toc: Definitions}
-----------------------------------------

Poleg blokov so v programu Latte na voljo tudi "definicije". Te so primerljive s funkcijami v običajnih programskih jezikih. Uporabne so za ponovno uporabo fragmentov predlog, da se ne ponavljamo.

Latte poskuša stvari poenostaviti, zato so definicije v osnovi enake blokom in **vse, kar je rečeno o blokih, velja tudi za definicije**. Od blokov se razlikujejo po tem, da:

1) zaprte so v oznake `{define}`.
2) se prikažejo samo, ko so vstavljene prek `{include}`
3) lahko jim določite parametre kot funkcijam v PHP

```latte
{block foo}<p>Hello</p>{/block}
{* prints: <p>Hello</p> *}

{define bar}<p>World</p>{/define}
{* ne natisne ničesar *}

{include bar}
{* prints: <p>World</p> *}
```

Predstavljajte si, da imate pomožno predlogo z zbirko definicij za risanje obrazcev HTML.

```latte .{file: forms.latte}
{define input, $name, $value, $type = 'text'}
	<input type={$type} name={$name} value={$value}>
{/define}

{define textarea, $name, $value}
	<textarea name={$name}>{$value}</textarea>
{/define}
```

Argumenti definicije so vedno neobvezni s privzeto vrednostjo `null`, razen če je določena privzeta vrednost (tukaj je `'text'` privzeta vrednost za `$type`). Vrste parametrov je mogoče tudi deklarirati: `{define input, string $name, ...}`.

Predloga z definicijami se naloži z uporabo [`{import}` |#horizontal-reuse]. Same definicije se prikažejo na [enak način kot bloki |#Printing Blocks]:

```latte
<p>{include input, 'password', null, 'password'}</p>
<p>{include textarea, 'comment'}</p>
```

Definicije nimajo dostopa do spremenljivk aktivnega konteksta, imajo pa dostop do globalnih spremenljivk.


Dinamična imena blokov .[#toc-dynamic-block-names]
--------------------------------------------------

Latte omogoča veliko prilagodljivost pri opredeljevanju blokov, saj je lahko ime bloka poljuben izraz PHP. Ta primer opredeljuje tri bloke z imeni `hi-Peter`, `hi-John` in `hi-Mary`:

```latte .{file: parent.latte}
{foreach [Peter, John, Mary] as $name}
	{block "hi-$name"}Hi, I am {$name}.{/block}
{/foreach}
```

Na primer, v podrejeni predlogi lahko na novo opredelimo samo en blok:

```latte .{file: child.latte}
{block hi-John}Hello. I am {$name}.{/block}
```

Tako bo rezultat videti takole:

```latte
Hi, I am Peter.
Hello. I am John.
Hi, I am Mary.
```


Preverjanje obstoja blokov `{ifset}` .{toc: Checking Block Existence}
---------------------------------------------------------------------

.[note]
Glej tudi [`{ifset $var}` |tags#ifset-elseifset]

S testom `{ifset blockname}` preverite, ali v trenutnem kontekstu obstaja blok (ali več blokov):

```latte
{ifset footer}
	...
{/ifset}

{ifset footer, header, main}
	...
{/ifset}
```

Kot ime bloka lahko uporabite spremenljivko ali kateri koli izraz v jeziku PHP. V tem primeru pred spremenljivko dodajte ključno besedo `block`, da bo jasno, da se ne preverja [spremenljivka |tags#ifset-elseifset]:

```latte
{ifset block $name}
	...
{/ifset}
```

Obstoj blokov vrne tudi funkcija [`hasBlock()` |functions#hasBlock]:

```latte
{if hasBlock(header) || hasBlock(footer)}
	...
{/if}
```


Nasveti .[#toc-tips]
--------------------
Tukaj je nekaj nasvetov za delo z bloki:

- Zadnjemu bloku najvišje ravni ni treba imeti zaključne oznake (blok se konča s koncem dokumenta). To poenostavi pisanje podrejenih predlog, ki imajo en primarni blok.

- Za večjo berljivost lahko po želji dodate ime oznaki `{/block}`, na primer `{/block footer}`. Vendar se mora ime ujemati z imenom bloka. V večjih predlogah vam ta tehnika pomaga videti, katere blokovne oznake so zaprte.

- V isti predlogi ne morete neposredno opredeliti več blokovnih oznak z istim imenom. To pa lahko dosežete z uporabo [dinamičnih imen blokov |#dynamic block names].

- Z uporabo [n:atributov |syntax#n:attributes] lahko opredelite bloke, kot so `<h1 n:block=title>Welcome to my awesome homepage</h1>`

- Bloki se lahko uporabljajo tudi brez imen samo za uporabo [filtrov |syntax#filters] na izhodu: `{block|strip} hello {/block}`


Vodoravna ponovna uporaba `{import}` .{toc: Horizontal Reuse}
=============================================================

Horizontalna ponovna uporaba je tretji mehanizem za ponovno uporabo in dedovanje v Latte. Omogoča nalaganje blokov iz drugih predlog. Podobno je, kot če bi v PHP ustvarili datoteko s pomožnimi funkcijami in jo nato naložili z uporabo spletne strani `require`.

Čeprav je dedovanje postavitve predloge ena od najmočnejših funkcij sistema Latte, je omejeno na preprosto dedovanje - predloga lahko razširi le eno drugo predlogo. Horizontalna ponovna uporaba je način za doseganje večkratnega dedovanja.

Imejmo nabor definicij blokov:

```latte .{file: blocks.latte}
{block sidebar}...{/block}

{block menu}...{/block}
```

Z ukazom `{import}` uvozimo vse bloke in [definicije, |#definitions] opredeljene v `blocks.latte`, v drugo predlogo:

```latte .{file: child.latte}
{import 'blocks.latte'}

{* stranska vrstica in menijski bloki se zdaj lahko uporabljajo *}
```

Če bloke uvozite v nadrejeno predlogo (npr. uporabite ukaz `{import}` v `layout.latte`), bodo bloki na voljo tudi v vseh podrejenih predlogah, kar je zelo priročno.

Predloga, ki je namenjena uvozu (npr. `blocks.latte`), ne sme [razširiti |#Layout Inheritance] druge predloge, tj. uporabite `{layout}`. Lahko pa uvozi druge predloge.

Oznaka `{import}` mora biti prva oznaka predloge za `{layout}`. Ime predloge je lahko kateri koli izraz PHP:

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

V posamezni predlogi lahko uporabite poljubno število izrazov `{import}`. Če dve uvoženi predlogi definirata isti blok, zmaga prva. Vendar ima največjo prednost glavna predloga, ki lahko prepiše kateri koli uvoženi blok.

Vsebino prepisanih blokov lahko ohranite tako, da blok vstavite na enak način kot [nadrejeni blok |#parent block]:

```latte
{layout 'layout.latte'}

{import 'blocks.latte'}

{block sidebar}
	{include parent}
{/block}

{block title}...{/block}
{block content}...{/block}
```

V tem primeru bo `{include parent}` pravilno poklical blok `sidebar` iz predloge `blocks.latte`.


Dedovanje enot `{embed}` .{toc: Unit Inheritance}
=================================================

Dedovanje enot prenaša idejo dedovanja postavitve na raven vsebinskih fragmentov. Medtem ko dedovanje postavitve deluje s "skeleti dokumentov", ki jih oživijo predloge otrok, dedovanje enot omogoča, da ustvarite skelete za manjše enote vsebine in jih ponovno uporabite kjerkoli želite.

Pri dedovanju enot je ključna oznaka `{embed}`. Združuje obnašanje oznak `{include}` in `{layout}`. Z njo lahko vključite vsebino druge predloge ali bloka in po želji posredujete spremenljivke, tako kot to počne `{include}`. Omogoča tudi prekrivanje katerega koli bloka, opredeljenega znotraj vključene predloge, kot to počne `{layout}`.

Za primer bomo uporabili element zložljive harmonike. Oglejmo si ogrodje elementa v predlogi `collapsible.latte`:

```latte
<section class="collapsible {$modifierClass}">
	<h4 class="collapsible__title">
		{block title}{/block}
	</h4>

	<div class="collapsible__content">
		{block content}{/block}
	</div>
</section>
```

Oznake `{block}` določajo dva bloka, ki ju lahko izpolnijo podrejene predloge. Da, tako kot v primeru starševske predloge v predlogi za dedovanje postavitve. Vidite tudi spremenljivko `$modifierClass`.

Uporabimo naš element v predlogi. Tu pride na vrsto `{embed}`. To je izjemno zmogljiv pripomoček, ki nam omogoča vse: vključiti vsebino predloge elementa, mu dodati spremenljivke in dodati bloke s prilagojenim HTML-jem:

```latte
{embed 'collapsible.latte', modifierClass: my-style}
	{block title}
		Hello World
	{/block}

	{block content}
		<p>Lorem ipsum dolor sit amet, consectetuer adipiscing
		elit. Nunc dapibus tortor vel mi dapibus sollicitudin.</p>
	{/block}
{/embed}
```

Rezultat je lahko videti takole:

```latte
<section class="collapsible my-style">
	<h4 class="collapsible__title">
		Hello World
	</h4>

	<div class="collapsible__content">
		<p>Lorem ipsum dolor sit amet, consectetuer adipiscing
		elit. Nunc dapibus tortor vel mi dapibus sollicitudin.</p>
	</div>
</section>
```

Bloki znotraj oznak embed tvorijo ločeno plast, neodvisno od drugih blokov. Zato imajo lahko enako ime kot blok zunaj vgradne oznake in nanje to nima nobenega vpliva. Z uporabo oznake [include |#Printing Blocks] znotraj oznak `{embed}` lahko vstavite tukaj ustvarjene bloke, bloke iz vstavljene predloge (ki *ne so* [lokalni |#Local Blocks]) in tudi bloke iz glavne predloge, ki *so* lokalni. Prav tako lahko [uvozite bloke |#Horizontal Reuse] iz drugih datotek:

```latte
{block outer}…{/block}
{block local hello}…{/block}

{embed 'collapsible.latte', modifierClass: my-style}
	{import 'blocks.latte'}

	{block inner}…{/block}

	{block title}
		{include inner} {* deluje, blok je definiran znotraj embed *}
		{include hello} {* deluje, blok je lokalni v tej predlogi *}
		{include content} {* deluje, blok je opredeljen v vdelani predlogi *}
		{include aBlockDefinedInImportedTemplate} {* deluje *}
		{include outer} {* ne deluje! - blok je v zunanji plasti *}
	{/block}
{/embed}
```

Vgrajene predloge nimajo dostopa do spremenljivk aktivnega konteksta, imajo pa dostop do globalnih spremenljivk.

S spletno stranjo `{embed}` lahko poleg predlog vstavite tudi druge bloke, zato bi lahko prejšnji primer zapisali takole:

```latte
{define collapsible}
<section class="collapsible {$modifierClass}">
	<h4 class="collapsible__title">
		{block title}{/block}
	</h4>
	...
</section>
{/define}


{embed collapsible, modifierClass: my-style}
	{block title}
		Hello World
	{/block}
	...
{/embed}
```

Če posredujemo izraz `{embed}` in ni jasno, ali gre za ime bloka ali datoteke, dodamo ključno besedo `block` ali `file`:

```latte
{embed block $name} ... {/embed}
```


Primeri uporabe .[#toc-use-cases]
=================================

V sistemu Latte obstajajo različne vrste dedovanja in ponovne uporabe kode. Za večjo jasnost povzemimo glavne koncepte:


`{include template}`
--------------------

**Primer uporabe:** Uporaba `header.latte` in `footer.latte` znotraj `layout.latte`.

`header.latte`

```latte
<nav>
   <div>Home</div>
   <div>About</div>
</nav>
```

`footer.latte`

```latte
<footer>
   <div>Copyright</div>
</footer>
```

`layout.latte`

```latte
{include 'header.latte'}

<main>{block main}{/block}</main>

{include 'footer.latte'}
```


`{layout}`
----------

**Primer uporabe**: Razširitev `layout.latte` znotraj `homepage.latte` in `about.latte`.

`layout.latte`

```latte
{include 'header.latte'}

<main>{block main}{/block}</main>

{include 'footer.latte'}
```

`homepage.latte`

```latte
{layout 'layout.latte'}

{block main}
	<p>Homepage</p>
{/block}
```

`about.latte`

```latte
{layout 'layout.latte'}

{block main}
	<p>About page</p>
{/block}
```


`{import}`
----------

**Primer uporabe**: `sidebar.latte` v `single.product.latte` in `single.service.latte`.

`sidebar.latte`

```latte
{block sidebar}<aside>This is sidebar</aside>{/block}
```

`single.product.latte`

```latte
{layout 'product.layout.latte'}

{import 'sidebar.latte'}

{block main}<main>Product page</main>{/block}
```

`single.service.latte`

```latte
{layout 'service.layout.latte'}

{import 'sidebar.latte'}

{block main}<main>Service page</main>{/block}
```


`{define}`
----------

**Primer uporabe**: Funkcija, ki dobi nekaj spremenljivk in izpiše nekaj oznak.

`form.latte`

```latte
{define form-input, $name, $value, $type = 'text'}
	<input type={$type} name={$name} value={$value}>
{/define}
```

`profile.service.latte`

```latte
{import 'form.latte'}

<form action="" method="post">
	<div>{include form-input, username}</div>
	<div>{include form-input, password}</div>
	<div>{include form-input, submit, Submit, submit}</div>
</form>
```


`{embed}`
---------

**Primer uporabe**: Vstavljanje `pagination.latte` v `product.table.latte` in `service.table.latte`.

`pagination.latte`

```latte
<div id="pagination">
	<div>{block first}{/block}</div>

	{for $i = $min + 1; $i < $max - 1; $i++}
		<div>{$i}</div>
	{/for}

	<div>{block last}{/block}</div>
</div>
```

`product.table.latte`

```latte
{embed 'pagination.latte', min: 1, max: $products->count}
	{block first}First Product Page{/block}
	{block last}Last Product Page{/block}
{/embed}
```

`service.table.latte`

```latte
{embed 'pagination.latte', min: 1, max: $services->count}
	{block first}First Service Page{/block}
	{block last}Last Service Page{/block}
{/embed}
```

Dedovanje predlog in ponovna uporabnost

Mehanizmi ponovne uporabnosti in dedovanja predlog povečujejo vašo produktivnost, saj vsaka predloga vsebuje le svojo edinstveno vsebino, ponavljajoči se elementi in strukture pa so ponovno uporabljeni. Predstavljamo tri koncepte: dedovanje postavitve, horizontalno ponovno uporabo in dedovanje enot.

Koncept dedovanja predlog Latte je podoben dedovanju razredov PHP. Določite starševsko predlogo, ki jo lahko druge družinske predloge razširijo in prekrijejo dele starševske predloge. To se odlično obnese, kadar si elementi delijo skupno strukturo. Se vam zdi zapleteno? Brez skrbi, ni.

Dedovanje postavitve {layout}

Oglejmo si dedovanje predlog postavitve s primerom. To je nadrejena predloga, ki jo bomo na primer poimenovali layout.latte in opredeljuje skeletni dokument HTML.

<!doctype html>
<html lang="en">
<head>
	<title>{block title}{/block}</title>
	<link rel="stylesheet" href="style.css">
</head>
<body>
	<div id="content">
		{block content}{/block}
	</div>
	<div id="footer">
		{block footer}&copy; Copyright 2008{/block}
	</div>
</body>
</html>

Oznake {block} opredeljujejo tri bloke, ki jih lahko zapolnijo podrejene predloge. Vse, kar naredi oznaka bloka, je, da pove gonilniku predloge, da lahko podrejena predloga prekrije te dele predloge z opredelitvijo lastnega bloka z istim imenom.

Otroška predloga je lahko videti takole:

{layout 'layout.latte'}

{block title}My amazing blog{/block}

{block content}
	<p>Welcome to my awesome homepage.</p>
{/block}

Pri tem je ključna oznaka {layout}. Ta sporoča mehanizmu predlog, da ta predloga „razširja“ drugo predlogo. Ko Latte upodablja to predlogo, najprej poišče nadrejeno – v tem primeru layout.latte.

Takrat bo mehanizem predloge opazil tri blokovne oznake v layout.latte in te bloke nadomestil z vsebino podrejene predloge. Upoštevajte, da ker otroška predloga ni opredelila bloka footer, se namesto tega uporabi vsebina iz starševske predloge. Vsebina znotraj oznake {block} v nadrejeni predlogi se vedno uporabi kot nadomestna možnost.

Rezultat je lahko videti takole:

<!doctype html>
<html lang="en">
<head>
	<title>My amazing blog</title>
	<link rel="stylesheet" href="style.css">
</head>
<body>
	<div id="content">
		<p>Welcome to my awesome homepage.</p>
	</div>
	<div id="footer">
		&copy; Copyright 2008
	</div>
</body>
</html>

V predlogi otroka se bloki lahko nahajajo samo na zgornji ravni ali znotraj drugega bloka, tj:

{block content}
	<h1>{block title}Welcome to my awesome homepage{/block}</h1>
{/block}

Prav tako bo blok vedno ustvarjen ne glede na to, ali je okoliški pogoj {if} ovrednoten kot true ali false. V nasprotju s tem, kar morda mislite, ta predloga opredeljuje blok.

{if false}
	{block head}
		<meta name="robots" content="noindex, follow">
	{/block}
{/if}

Če želite, da se izpis znotraj bloka prikaže pogojno, namesto tega uporabite naslednje:

{block head}
	{if $condition}
		<meta name="robots" content="noindex, follow">
	{/if}
{/block}

Podatki zunaj blokov v podrejeni predlogi se izvedejo pred prikazom predloge za postavitev, zato jo lahko uporabite za opredelitev spremenljivk, kot je {var $foo = bar}, in širjenje podatkov v celotno dedno verigo:

{layout 'layout.latte'}
{var $robots = noindex}

...

Večnivojsko dedovanje

Uporabite lahko toliko ravni dedovanja, kolikor jih potrebujete. Eden od pogostih načinov uporabe dedovanja postavitve je naslednji tristopenjski pristop:

  1. Ustvarite predlogo layout.latte, ki vsebuje glavni videz vašega spletnega mesta.
  2. Ustvarite predlogo layout-SECTIONNAME.latte za vsak razdelek svojega spletnega mesta. Na primer layout-news.latte, layout-blog.latte itd. Vse te predloge razširjajo spletno stran layout.latte in vključujejo sloge/oblikovanje, značilne za posamezno poglavje.
  3. Ustvarite posamezne predloge za vsako vrsto strani, na primer za novičarski članek ali zapis na blogu. Te predloge razširjajo ustrezno predlogo za razdelek.

Dinamično dedovanje postavitve

Kot ime nadrejene predloge lahko uporabite spremenljivko ali kateri koli izraz PHP, zato se lahko dedovanje obnaša dinamično:

{layout $standalone ? 'minimum.latte' : 'layout.latte'}

Uporabite lahko tudi API Latte za samodejno izbiro predloge za postavitev.

Nasveti

Tukaj je nekaj nasvetov za delo z dedovanjem postavitve:

  • Če v predlogi uporabite {layout}, mora biti to prva oznaka v predlogi.
  • Postavitev lahko iščete samodejno (kot v predstavitvah). Če v tem primeru predloga ne sme imeti postavitve, se to označi z oznako {layout none}.
  • Oznaka {layout} ima vzdevek {extends}.
  • Ime datoteke razširjene predloge je odvisno od programa za nalaganje predlog.
  • Na voljo je lahko poljubno število blokov. Ne pozabite, da podrejenim predlogam ni treba opredeliti vseh nadrejenih blokov, zato lahko v več blokov vnesete razumne privzete nastavitve, pozneje pa opredelite le tiste, ki jih potrebujete.

Bloki {block}

Glej tudi anonimni {block}

Blok omogoča spreminjanje načina upodabljanja določenega dela predloge, vendar na noben način ne posega v okoliško logiko. Z naslednjim primerom ponazorimo, kako blok deluje in, kar je še pomembneje, kako ne deluje:

{foreach $posts as $post}
{block post}
	<h1>{$post->title}</h1>
	<p>{$post->body}</p>
{/block}
{/foreach}

Če to predlogo prikažete, bo rezultat popolnoma enak z oznakami bloka ali brez njih. Bloki imajo dostop do spremenljivk iz zunanjih obsegov. To je le način, da ga lahko podrejena predloga prekrije:

{layout 'parent.Latte'}

{block post}
	<article>
		<header>{$post->title}</header>
		<section>{$post->text}</section>
	</article>
{/block}

Sedaj bo zanka pri upodabljanju podrejene predloge uporabila blok, opredeljen v podrejeni predlogi child.Latte, namesto bloka, opredeljenega v osnovni predlogi parent.Latte; izvedena predloga je nato enakovredna naslednji:

{foreach $posts as $post}
	<article>
		<header>{$post->title}</header>
		<section>{$post->text}</section>
	</article>
{/foreach}

Če pa znotraj poimenovanega bloka ustvarimo novo spremenljivko ali zamenjamo vrednost obstoječe, bo sprememba vidna samo znotraj bloka:

{var $foo = 'foo'}
{block post}
	{do $foo = 'new value'}
	{var $bar = 'bar'}
{/block}

foo: {$foo}                  // prints: foo
bar: {$bar ?? 'not defined'} // prints: not defined

Vsebino bloka lahko spremenimo s filtri. Naslednji primer odstrani ves HTML in ga naslovi:

<title>{block title|stripHtml|capitalize}...{/block}</title>

Oznaka je lahko zapisana tudi kot n:attribute:

<article n:block=post>
	...
</article>

Lokalni bloki

Vsak blok prekrije vsebino nadrejenega bloka z istim imenom. Razen lokalnih blokov. Ti so nekaj podobnega kot zasebne metode v razredu. Ustvarite lahko predlogo, ne da bi vas skrbelo, da bi jih – zaradi naključja imen blokov – druga predloga prepisala.

{block local helper}
	...
{/block}

Tiskanje blokov {include}

Glej tudi {include file}

Če želite blok natisniti na določenem mestu, uporabite oznako {include blockname}:

<title>{block title}{/block}</title>

<h1>{include title}</h1>

Prikažete lahko tudi blok iz druge predloge:

{include footer from 'main.latte'}

Izpisani blok nima dostopa do spremenljivk aktivnega konteksta, razen če je blok definiran v isti datoteki, v katero je vključen. Imajo pa dostop do globalnih spremenljivk.

Spremenljivke lahko bloku posredujete na naslednji način:

{include footer, foo: bar, id: 123}

Kot ime bloka lahko uporabite spremenljivko ali kateri koli izraz v PHP. V tem primeru pred spremenljivko dodajte ključno besedo block, da se ob sestavljanju ve, da gre za blok, in ne za vstavljanje predloge, katere ime je lahko tudi v spremenljivki:

{var $name = footer}
{include block $name}

Blok se lahko izpiše tudi znotraj samega sebe, kar je uporabno na primer pri upodabljanju drevesne strukture:

{define menu, $items}
<ul>
	{foreach $items as $item}
		<li>
		{if is_array($item)}
			{include menu, $item}
		{else}
			{$item}
		{/if}
		</li>
	{/foreach}
</ul>
{/define}

Namesto {include menu, ...} lahko zapišemo tudi {include this, ...}, kjer this pomeni trenutni blok.

Natisnjeno vsebino lahko spreminjamo s filtri. Naslednji primer odstrani ves HTML in ga označi z naslovi:

<title>{include heading|stripHtml|capitalize}</title>

Nadrejeni blok

Če morate vsebino bloka izpisati iz nadrejene predloge, bo to storila izjava {include parent}. To je uporabno, če želite dodati vsebino nadrejenega bloka, namesto da bi ga v celoti prepisali.

{block footer}
	{include parent}
	<a href="https://github.com/nette">GitHub</a>
	<a href="https://twitter.com/nettefw">Twitter</a>
{/block}

Definicije {define}

Poleg blokov so v programu Latte na voljo tudi „definicije“. Te so primerljive s funkcijami v običajnih programskih jezikih. Uporabne so za ponovno uporabo fragmentov predlog, da se ne ponavljamo.

Latte poskuša stvari poenostaviti, zato so definicije v osnovi enake blokom in vse, kar je rečeno o blokih, velja tudi za definicije. Od blokov se razlikujejo po tem, da:

  1. zaprte so v oznake {define}.
  2. se prikažejo samo, ko so vstavljene prek {include}
  3. lahko jim določite parametre kot funkcijam v PHP
{block foo}<p>Hello</p>{/block}
{* prints: <p>Hello</p> *}

{define bar}<p>World</p>{/define}
{* ne natisne ničesar *}

{include bar}
{* prints: <p>World</p> *}

Predstavljajte si, da imate pomožno predlogo z zbirko definicij za risanje obrazcev HTML.

{define input, $name, $value, $type = 'text'}
	<input type={$type} name={$name} value={$value}>
{/define}

{define textarea, $name, $value}
	<textarea name={$name}>{$value}</textarea>
{/define}

Argumenti definicije so vedno neobvezni s privzeto vrednostjo null, razen če je določena privzeta vrednost (tukaj je 'text' privzeta vrednost za $type). Vrste parametrov je mogoče tudi deklarirati: {define input, string $name, ...}.

Predloga z definicijami se naloži z uporabo {import}. Same definicije se prikažejo na enak način kot bloki:

<p>{include input, 'password', null, 'password'}</p>
<p>{include textarea, 'comment'}</p>

Definicije nimajo dostopa do spremenljivk aktivnega konteksta, imajo pa dostop do globalnih spremenljivk.

Dinamična imena blokov

Latte omogoča veliko prilagodljivost pri opredeljevanju blokov, saj je lahko ime bloka poljuben izraz PHP. Ta primer opredeljuje tri bloke z imeni hi-Peter, hi-John in hi-Mary:

{foreach [Peter, John, Mary] as $name}
	{block "hi-$name"}Hi, I am {$name}.{/block}
{/foreach}

Na primer, v podrejeni predlogi lahko na novo opredelimo samo en blok:

{block hi-John}Hello. I am {$name}.{/block}

Tako bo rezultat videti takole:

Hi, I am Peter.
Hello. I am John.
Hi, I am Mary.

Preverjanje obstoja blokov {ifset}

Glej tudi {ifset $var}

S testom {ifset blockname} preverite, ali v trenutnem kontekstu obstaja blok (ali več blokov):

{ifset footer}
	...
{/ifset}

{ifset footer, header, main}
	...
{/ifset}

Kot ime bloka lahko uporabite spremenljivko ali kateri koli izraz v jeziku PHP. V tem primeru pred spremenljivko dodajte ključno besedo block, da bo jasno, da se ne preverja spremenljivka:

{ifset block $name}
	...
{/ifset}

Obstoj blokov vrne tudi funkcija hasBlock():

{if hasBlock(header) || hasBlock(footer)}
	...
{/if}

Nasveti

Tukaj je nekaj nasvetov za delo z bloki:

  • Zadnjemu bloku najvišje ravni ni treba imeti zaključne oznake (blok se konča s koncem dokumenta). To poenostavi pisanje podrejenih predlog, ki imajo en primarni blok.
  • Za večjo berljivost lahko po želji dodate ime oznaki {/block}, na primer {/block footer}. Vendar se mora ime ujemati z imenom bloka. V večjih predlogah vam ta tehnika pomaga videti, katere blokovne oznake so zaprte.
  • V isti predlogi ne morete neposredno opredeliti več blokovnih oznak z istim imenom. To pa lahko dosežete z uporabo dinamičnih imen blokov.
  • Z uporabo n:atributov lahko opredelite bloke, kot so <h1 n:block=title>Welcome to my awesome homepage</h1>
  • Bloki se lahko uporabljajo tudi brez imen samo za uporabo filtrov na izhodu: {block|strip} hello {/block}

Vodoravna ponovna uporaba {import}

Horizontalna ponovna uporaba je tretji mehanizem za ponovno uporabo in dedovanje v Latte. Omogoča nalaganje blokov iz drugih predlog. Podobno je, kot če bi v PHP ustvarili datoteko s pomožnimi funkcijami in jo nato naložili z uporabo spletne strani require.

Čeprav je dedovanje postavitve predloge ena od najmočnejših funkcij sistema Latte, je omejeno na preprosto dedovanje – predloga lahko razširi le eno drugo predlogo. Horizontalna ponovna uporaba je način za doseganje večkratnega dedovanja.

Imejmo nabor definicij blokov:

{block sidebar}...{/block}

{block menu}...{/block}

Z ukazom {import} uvozimo vse bloke in definicije, opredeljene v blocks.latte, v drugo predlogo:

{import 'blocks.latte'}

{* stranska vrstica in menijski bloki se zdaj lahko uporabljajo *}

Če bloke uvozite v nadrejeno predlogo (npr. uporabite ukaz {import} v layout.latte), bodo bloki na voljo tudi v vseh podrejenih predlogah, kar je zelo priročno.

Predloga, ki je namenjena uvozu (npr. blocks.latte), ne sme razširiti druge predloge, tj. uporabite {layout}. Lahko pa uvozi druge predloge.

Oznaka {import} mora biti prva oznaka predloge za {layout}. Ime predloge je lahko kateri koli izraz PHP:

{import $ajax ? 'ajax.latte' : 'not-ajax.latte'}

V posamezni predlogi lahko uporabite poljubno število izrazov {import}. Če dve uvoženi predlogi definirata isti blok, zmaga prva. Vendar ima največjo prednost glavna predloga, ki lahko prepiše kateri koli uvoženi blok.

Vsebino prepisanih blokov lahko ohranite tako, da blok vstavite na enak način kot nadrejeni blok:

{layout 'layout.latte'}

{import 'blocks.latte'}

{block sidebar}
	{include parent}
{/block}

{block title}...{/block}
{block content}...{/block}

V tem primeru bo {include parent} pravilno poklical blok sidebar iz predloge blocks.latte.

Dedovanje enot {embed}

Dedovanje enot prenaša idejo dedovanja postavitve na raven vsebinskih fragmentov. Medtem ko dedovanje postavitve deluje s „skeleti dokumentov“, ki jih oživijo predloge otrok, dedovanje enot omogoča, da ustvarite skelete za manjše enote vsebine in jih ponovno uporabite kjerkoli želite.

Pri dedovanju enot je ključna oznaka {embed}. Združuje obnašanje oznak {include} in {layout}. Z njo lahko vključite vsebino druge predloge ali bloka in po želji posredujete spremenljivke, tako kot to počne {include}. Omogoča tudi prekrivanje katerega koli bloka, opredeljenega znotraj vključene predloge, kot to počne {layout}.

Za primer bomo uporabili element zložljive harmonike. Oglejmo si ogrodje elementa v predlogi collapsible.latte:

<section class="collapsible {$modifierClass}">
	<h4 class="collapsible__title">
		{block title}{/block}
	</h4>

	<div class="collapsible__content">
		{block content}{/block}
	</div>
</section>

Oznake {block} določajo dva bloka, ki ju lahko izpolnijo podrejene predloge. Da, tako kot v primeru starševske predloge v predlogi za dedovanje postavitve. Vidite tudi spremenljivko $modifierClass.

Uporabimo naš element v predlogi. Tu pride na vrsto {embed}. To je izjemno zmogljiv pripomoček, ki nam omogoča vse: vključiti vsebino predloge elementa, mu dodati spremenljivke in dodati bloke s prilagojenim HTML-jem:

{embed 'collapsible.latte', modifierClass: my-style}
	{block title}
		Hello World
	{/block}

	{block content}
		<p>Lorem ipsum dolor sit amet, consectetuer adipiscing
		elit. Nunc dapibus tortor vel mi dapibus sollicitudin.</p>
	{/block}
{/embed}

Rezultat je lahko videti takole:

<section class="collapsible my-style">
	<h4 class="collapsible__title">
		Hello World
	</h4>

	<div class="collapsible__content">
		<p>Lorem ipsum dolor sit amet, consectetuer adipiscing
		elit. Nunc dapibus tortor vel mi dapibus sollicitudin.</p>
	</div>
</section>

Bloki znotraj oznak embed tvorijo ločeno plast, neodvisno od drugih blokov. Zato imajo lahko enako ime kot blok zunaj vgradne oznake in nanje to nima nobenega vpliva. Z uporabo oznake include znotraj oznak {embed} lahko vstavite tukaj ustvarjene bloke, bloke iz vstavljene predloge (ki ne so lokalni) in tudi bloke iz glavne predloge, ki so lokalni. Prav tako lahko uvozite bloke iz drugih datotek:

{block outer}…{/block}
{block local hello}…{/block}

{embed 'collapsible.latte', modifierClass: my-style}
	{import 'blocks.latte'}

	{block inner}…{/block}

	{block title}
		{include inner} {* deluje, blok je definiran znotraj embed *}
		{include hello} {* deluje, blok je lokalni v tej predlogi *}
		{include content} {* deluje, blok je opredeljen v vdelani predlogi *}
		{include aBlockDefinedInImportedTemplate} {* deluje *}
		{include outer} {* ne deluje! - blok je v zunanji plasti *}
	{/block}
{/embed}

Vgrajene predloge nimajo dostopa do spremenljivk aktivnega konteksta, imajo pa dostop do globalnih spremenljivk.

S spletno stranjo {embed} lahko poleg predlog vstavite tudi druge bloke, zato bi lahko prejšnji primer zapisali takole:

{define collapsible}
<section class="collapsible {$modifierClass}">
	<h4 class="collapsible__title">
		{block title}{/block}
	</h4>
	...
</section>
{/define}


{embed collapsible, modifierClass: my-style}
	{block title}
		Hello World
	{/block}
	...
{/embed}

Če posredujemo izraz {embed} in ni jasno, ali gre za ime bloka ali datoteke, dodamo ključno besedo block ali file:

{embed block $name} ... {/embed}

Primeri uporabe

V sistemu Latte obstajajo različne vrste dedovanja in ponovne uporabe kode. Za večjo jasnost povzemimo glavne koncepte:

{include template}

Primer uporabe: Uporaba header.latte in footer.latte znotraj layout.latte.

header.latte

<nav>
   <div>Home</div>
   <div>About</div>
</nav>

footer.latte

<footer>
   <div>Copyright</div>
</footer>

layout.latte

{include 'header.latte'}

<main>{block main}{/block}</main>

{include 'footer.latte'}

{layout}

Primer uporabe: Razširitev layout.latte znotraj homepage.latte in about.latte.

layout.latte

{include 'header.latte'}

<main>{block main}{/block}</main>

{include 'footer.latte'}

homepage.latte

{layout 'layout.latte'}

{block main}
	<p>Homepage</p>
{/block}

about.latte

{layout 'layout.latte'}

{block main}
	<p>About page</p>
{/block}

{import}

Primer uporabe: sidebar.latte v single.product.latte in single.service.latte.

sidebar.latte

{block sidebar}<aside>This is sidebar</aside>{/block}

single.product.latte

{layout 'product.layout.latte'}

{import 'sidebar.latte'}

{block main}<main>Product page</main>{/block}

single.service.latte

{layout 'service.layout.latte'}

{import 'sidebar.latte'}

{block main}<main>Service page</main>{/block}

{define}

Primer uporabe: Funkcija, ki dobi nekaj spremenljivk in izpiše nekaj oznak.

form.latte

{define form-input, $name, $value, $type = 'text'}
	<input type={$type} name={$name} value={$value}>
{/define}

profile.service.latte

{import 'form.latte'}

<form action="" method="post">
	<div>{include form-input, username}</div>
	<div>{include form-input, password}</div>
	<div>{include form-input, submit, Submit, submit}</div>
</form>

{embed}

Primer uporabe: Vstavljanje pagination.latte v product.table.latte in service.table.latte.

pagination.latte

<div id="pagination">
	<div>{block first}{/block}</div>

	{for $i = $min + 1; $i < $max - 1; $i++}
		<div>{$i}</div>
	{/for}

	<div>{block last}{/block}</div>
</div>

product.table.latte

{embed 'pagination.latte', min: 1, max: $products->count}
	{block first}First Product Page{/block}
	{block last}Last Product Page{/block}
{/embed}

service.table.latte

{embed 'pagination.latte', min: 1, max: $services->count}
	{block first}First Service Page{/block}
	{block last}Last Service Page{/block}
{/embed}