Nette Documentation Preview

syntax
Κληρονομικότητα προτύπων και επαναχρησιμοποίηση
***********************************************

.[perex]
Οι μηχανισμοί επαναχρησιμοποίησης προτύπων και κληρονομικότητας είναι εδώ για να ενισχύσουν την παραγωγικότητά σας, επειδή κάθε πρότυπο περιέχει μόνο το μοναδικό του περιεχόμενο και τα επαναλαμβανόμενα στοιχεία και δομές επαναχρησιμοποιούνται. Παρουσιάζουμε τρεις έννοιες: [κληρονομικότητα διάταξης |#layout inheritance], [οριζόντια επαναχρησιμοποίηση |#horizontal reuse] και [κληρονομικότητα μονάδων |#unit inheritance].

Η έννοια της κληρονομικότητας προτύπων Latte είναι παρόμοια με την κληρονομικότητα κλάσεων της PHP. Ορίζετε ένα **πρότυπο γονέα** από το οποίο άλλα **πρότυπα-παιδιά** μπορούν να επεκταθούν και να αντικαταστήσουν τμήματα του προτύπου γονέα. Λειτουργεί εξαιρετικά όταν τα στοιχεία μοιράζονται μια κοινή δομή. Ακούγεται περίπλοκο; Μην ανησυχείτε, δεν είναι.


Κληρονομικότητα διάταξης `{layout}` .{toc: Layout Inheritance}
==============================================================

Ας δούμε την κληρονομικότητα προτύπων διάταξης ξεκινώντας με ένα παράδειγμα. Πρόκειται για ένα πρότυπο γονέα το οποίο θα ονομάσουμε για παράδειγμα `layout.latte` και ορίζει ένα έγγραφο-σκελετό 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>
```

Οι ετικέτες `{block}` ορίζουν τρία μπλοκ που μπορούν να συμπληρώσουν τα πρότυπα-παιδιά. Το μόνο που κάνει η ετικέτα μπλοκ είναι να πει στη μηχανή προτύπων ότι ένα πρότυπο παιδί μπορεί να παρακάμψει αυτά τα τμήματα του προτύπου ορίζοντας το δικό του μπλοκ με το ίδιο όνομα.

Ένα υποκατάστατο πρότυπο μπορεί να μοιάζει ως εξής:

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

{block title}My amazing blog{/block}

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

Η ετικέτα `{layout}` είναι το κλειδί εδώ. Λέει στη μηχανή προτύπων ότι αυτό το πρότυπο "επεκτείνει" ένα άλλο πρότυπο. Όταν το Latte αποδίδει αυτό το πρότυπο, πρώτα εντοπίζει τον γονέα - σε αυτή την περίπτωση, το `layout.latte`.

Σε αυτό το σημείο, η μηχανή προτύπων θα παρατηρήσει τις τρεις ετικέτες μπλοκ στο `layout.latte` και θα αντικαταστήσει αυτά τα μπλοκ με τα περιεχόμενα του προτύπου-παιδί. Σημειώστε ότι εφόσον το πρότυπο παιδί δεν όρισε το μπλοκ *footer*, αντί αυτού χρησιμοποιείται το περιεχόμενο από το πρότυπο γονέα. Το περιεχόμενο μέσα σε μια ετικέτα `{block}` σε ένα γονικό πρότυπο χρησιμοποιείται πάντα ως εφεδρικό.

Η έξοδος μπορεί να μοιάζει ως εξής:

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

Σε ένα πρότυπο παιδί, τα μπλοκ μπορούν να βρίσκονται μόνο είτε στο ανώτερο επίπεδο είτε μέσα σε ένα άλλο μπλοκ, δηλ:

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

Επίσης, ένα μπλοκ θα δημιουργείται πάντα στο ανεξάρτητα από το αν η συνθήκη που το περιβάλλει `{if}` αξιολογείται ως αληθής ή ψευδής. Σε αντίθεση με ό,τι μπορεί να νομίζετε, αυτό το πρότυπο ορίζει ένα μπλοκ.

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

Αν θέλετε η έξοδος μέσα στο μπλοκ να εμφανίζεται υπό συνθήκη, χρησιμοποιήστε αντ' αυτού τα ακόλουθα:

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

Τα δεδομένα έξω από ένα μπλοκ σε ένα πρότυπο παιδί εκτελούνται πριν από την απόδοση του προτύπου διάταξης, επομένως μπορείτε να το χρησιμοποιήσετε για να ορίσετε μεταβλητές όπως το `{var $foo = bar}` και να διαδώσετε δεδομένα σε ολόκληρη την αλυσίδα κληρονομικότητας:

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

...
```


Κληρονομικότητα πολλαπλών επιπέδων .[#toc-multilevel-inheritance]
-----------------------------------------------------------------
Μπορείτε να χρησιμοποιήσετε όσα επίπεδα κληρονομικότητας χρειάζεστε. Ένας συνηθισμένος τρόπος χρήσης της κληρονομικότητας διάταξης είναι η ακόλουθη προσέγγιση τριών επιπέδων:

1) Δημιουργήστε ένα πρότυπο `layout.latte` που κρατάει την κύρια εμφάνιση και αίσθηση του ιστότοπού σας.
2) Δημιουργήστε ένα πρότυπο `layout-SECTIONNAME.latte` για κάθε τμήμα του ιστότοπού σας. Για παράδειγμα, `layout-news.latte`, `layout-blog.latte` κ.λπ. Όλα αυτά τα πρότυπα επεκτείνουν το `layout.latte` και περιλαμβάνουν στυλ/σχεδιασμό για κάθε τμήμα.
3) Δημιουργήστε μεμονωμένα πρότυπα για κάθε τύπο σελίδας, όπως ένα άρθρο ειδήσεων ή μια καταχώρηση σε ιστολόγιο. Αυτά τα πρότυπα επεκτείνουν το κατάλληλο πρότυπο τμήματος.


Κληρονομικότητα δυναμικής διάταξης .[#toc-dynamic-layout-inheritance]
---------------------------------------------------------------------
Μπορείτε να χρησιμοποιήσετε μια μεταβλητή ή οποιαδήποτε έκφραση PHP ως όνομα του προτύπου γονέα, ώστε η κληρονομικότητα να συμπεριφέρεται δυναμικά:

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

Μπορείτε επίσης να χρησιμοποιήσετε το API Latte για να επιλέξετε [αυτόματα |develop#automatic-layout-lookup] το πρότυπο διάταξης.


Συμβουλές .[#toc-tips]
----------------------
Ακολουθούν ορισμένες συμβουλές για την εργασία με την κληρονομικότητα διάταξης:

- Εάν χρησιμοποιείτε το `{layout}` σε ένα πρότυπο, πρέπει να είναι η πρώτη ετικέτα προτύπου σε αυτό το πρότυπο.

- Η διάταξη μπορεί να [αναζητηθεί αυτόματα |develop#automatic-layout-lookup] (όπως στους [παρουσιαστές |application:templates#Template Lookup]). Σε αυτή την περίπτωση, αν το πρότυπο δεν πρέπει να έχει διάταξη, θα το υποδείξει με την ετικέτα `{layout none}`.

- Η ετικέτα `{layout}` έχει ψευδώνυμο `{extends}`.

- Το όνομα αρχείου του εκτεταμένου προτύπου εξαρτάται από τον [φορτωτή προτύπων |extending-latte#Loaders].

- Μπορείτε να έχετε όσα μπλοκ θέλετε. Θυμηθείτε, τα υποδείγματα-παιδιά δεν χρειάζεται να ορίζουν όλα τα μπλοκ γονέων, οπότε μπορείτε να συμπληρώσετε λογικές προεπιλογές σε πολλά μπλοκ και στη συνέχεια να ορίσετε μόνο αυτά που χρειάζεστε αργότερα.


Μπλοκ `{block}` .{toc: Blocks}
==============================

.[note]
Βλέπε επίσης ανώνυμο [`{block}` |tags#block]

Ένα μπλοκ παρέχει έναν τρόπο να αλλάξετε τον τρόπο απόδοσης ενός συγκεκριμένου τμήματος ενός προτύπου, αλλά δεν παρεμβαίνει με κανέναν τρόπο στη λογική γύρω από αυτό. Ας πάρουμε το παρακάτω παράδειγμα για να δείξουμε πώς λειτουργεί ένα μπλοκ και κυρίως πώς δεν λειτουργεί:

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

Αν αποδώσετε αυτό το πρότυπο, το αποτέλεσμα θα είναι ακριβώς το ίδιο με ή χωρίς τις ετικέτες μπλοκ. Τα μπλοκ έχουν πρόσβαση σε μεταβλητές από εξωτερικά πεδία εφαρμογής. Είναι απλώς ένας τρόπος για να το κάνετε να μπορεί να παρακαμφθεί από ένα πρότυπο-παιδί:

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

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

Τώρα, κατά την απόδοση του παιδικού προτύπου, ο βρόχος θα χρησιμοποιήσει το μπλοκ που ορίζεται στο παιδικό πρότυπο `child.Latte` αντί για αυτό που ορίζεται στο βασικό `parent.Latte`; το εκτελούμενο πρότυπο είναι τότε ισοδύναμο με το ακόλουθο:

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

Ωστόσο, αν δημιουργήσουμε μια νέα μεταβλητή μέσα σε ένα μπλοκ με όνομα ή αντικαταστήσουμε μια τιμή μιας υπάρχουσας, η αλλαγή θα είναι ορατή μόνο μέσα στο μπλοκ:

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

Τα περιεχόμενα του μπλοκ μπορούν να τροποποιηθούν από [φίλτρα |syntax#filters]. Το ακόλουθο παράδειγμα αφαιρεί όλη την HTML και την αλλαγή τίτλου:

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

Η ετικέτα μπορεί επίσης να γραφτεί ως [n:attribute |syntax#n:attributes]:

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


Τοπικά μπλοκ .[#toc-local-blocks]
---------------------------------

Κάθε μπλοκ παρακάμπτει το περιεχόμενο του γονικού μπλοκ με το ίδιο όνομα. Εκτός από τα τοπικά μπλοκ. Είναι κάτι σαν τις ιδιωτικές μεθόδους της κλάσης. Μπορείτε να δημιουργήσετε ένα πρότυπο χωρίς να ανησυχείτε ότι - λόγω σύμπτωσης των ονομάτων των μπλοκ - θα αντικατασταθούν από το δεύτερο πρότυπο.

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


Εκτύπωση μπλοκ `{include}` .{toc: Printing Blocks}
--------------------------------------------------

.[note]
Βλέπε επίσης [`{include file}` |tags#include]

Για να εκτυπώσετε ένα μπλοκ σε ένα συγκεκριμένο σημείο, χρησιμοποιήστε την ετικέτα `{include blockname}`:

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

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

Μπορείτε επίσης να εμφανίσετε μπλοκ από άλλο πρότυπο:

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

εκτός αν το μπλοκ έχει οριστεί στο ίδιο αρχείο όπου περιλαμβάνεται. Ωστόσο, έχουν πρόσβαση στις παγκόσμιες μεταβλητές.

Μπορείτε να περάσετε μεταβλητές στο μπλοκ με τον ακόλουθο τρόπο:

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

Μπορείτε να χρησιμοποιήσετε μια μεταβλητή ή οποιαδήποτε έκφραση στην PHP ως όνομα μπλοκ. Σε αυτή την περίπτωση, προσθέστε τη λέξη-κλειδί `block` πριν από τη μεταβλητή, ώστε να είναι γνωστό κατά τη μεταγλώττιση ότι πρόκειται για μπλοκ και όχι για [insert template |tags#include], το όνομα του οποίου θα μπορούσε επίσης να βρίσκεται στη μεταβλητή:

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

Το μπλοκ μπορεί επίσης να εκτυπωθεί μέσα στον εαυτό του, κάτι που είναι χρήσιμο, για παράδειγμα, κατά την απόδοση μιας δενδρικής δομής:

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

Αντί του `{include menu, ...}` μπορούμε επίσης να γράψουμε `{include this, ...}` όπου `this` σημαίνει τρέχον μπλοκ.

Το εκτυπωμένο περιεχόμενο μπορεί να τροποποιηθεί με [φίλτρα |syntax#filters]. Το ακόλουθο παράδειγμα αφαιρεί όλη την HTML και την αλλαγή του τίτλου:

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


Γονικό μπλοκ .[#toc-parent-block]
---------------------------------

Εάν πρέπει να εκτυπώσετε το περιεχόμενο του μπλοκ από το γονικό πρότυπο, η δήλωση `{include parent}` θα κάνει το κόλπο. Αυτό είναι χρήσιμο αν θέλετε να προσθέσετε στα περιεχόμενα ενός γονικού μπλοκ αντί να το παρακάμψετε πλήρως.

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


Ορισμοί `{define}` .{toc: Definitions}
--------------------------------------

Εκτός από τα μπλοκ, υπάρχουν επίσης "ορισμοί" στο Latte. Είναι συγκρίσιμοι με τις συναρτήσεις στις κανονικές γλώσσες προγραμματισμού. Είναι χρήσιμοι για την επαναχρησιμοποίηση τμημάτων προτύπων για να μην επαναλαμβάνεστε.

Η Latte προσπαθεί να κρατήσει τα πράγματα απλά, οπότε βασικά οι ορισμοί είναι το ίδιο με τα μπλοκ, και **ό,τι λέγεται για τα μπλοκ ισχύει και για τους ορισμούς**. Διαφέρουν από τα μπλοκ σε αυτό:

1) περικλείονται σε ετικέτες `{define}`
2) αποδίδονται μόνο όταν εισάγονται μέσω `{include}`
3) μπορείτε να ορίσετε παραμέτρους για αυτά όπως οι συναρτήσεις στην PHP

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

{define bar}<p>World</p>{/define}
{* δεν εκτυπώνει τίποτα *}

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

Φανταστείτε ότι έχετε ένα βοηθητικό πρότυπο με μια συλλογή ορισμών για το πώς να σχεδιάζετε φόρμες 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}
```

Τα επιχειρήματα ενός ορισμού είναι πάντοτε προαιρετικά με προεπιλεγμένη τιμή `null`, εκτός εάν έχει καθοριστεί προεπιλεγμένη τιμή (εδώ `'text'` είναι η προεπιλεγμένη τιμή για το `$type`). Οι τύποι παραμέτρων μπορούν επίσης να δηλωθούν: `{define input, string $name, ...}`.

Το πρότυπο με τους ορισμούς φορτώνεται χρησιμοποιώντας [`{import}` |#horizontal-reuse]. Οι ίδιοι οι ορισμοί απεικονίζονται με τον [ίδιο τρόπο όπως και τα μπλοκ |#Printing Blocks]:

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

Οι ορισμοί δεν έχουν πρόσβαση στις μεταβλητές του ενεργού πλαισίου, αλλά έχουν πρόσβαση σε παγκόσμιες μεταβλητές.


Δυναμικά ονόματα μπλοκ .[#toc-dynamic-block-names]
--------------------------------------------------

Η Latte επιτρέπει μεγάλη ευελιξία στον ορισμό των μπλοκ, επειδή το όνομα του μπλοκ μπορεί να είναι οποιαδήποτε έκφραση της PHP. Αυτό το παράδειγμα ορίζει τρία μπλοκ με τα ονόματα `hi-Peter`, `hi-John` και `hi-Mary`:

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

Για παράδειγμα, μπορούμε να επαναπροσδιορίσουμε μόνο ένα μπλοκ σε ένα πρότυπο παιδί:

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

Έτσι, η έξοδος θα μοιάζει με αυτό:

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


Έλεγχος ύπαρξης μπλοκ `{ifset}` .{toc: Checking Block Existence}
----------------------------------------------------------------

.[note]
Βλέπε επίσης [`{ifset $var}` |tags#ifset-elseifset]

Χρησιμοποιήστε τη δοκιμή `{ifset blockname}` για να ελέγξετε αν ένα μπλοκ (ή περισσότερα μπλοκ) υπάρχει στο τρέχον πλαίσιο:

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

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

Μπορείτε να χρησιμοποιήσετε μια μεταβλητή ή οποιαδήποτε έκφραση στην PHP ως όνομα μπλοκ. Σε αυτή την περίπτωση, προσθέστε τη λέξη-κλειδί `block` πριν από τη μεταβλητή για να καταστήσετε σαφές ότι δεν είναι η [μεταβλητή |tags#ifset-elseifset] που ελέγχεται:

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

Η ύπαρξη μπλοκ επιστρέφεται επίσης από τη συνάρτηση [`hasBlock()` |functions#hasBlock]:

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


Συμβουλές .[#toc-tips]
----------------------
Ακολουθούν μερικές συμβουλές για την εργασία με μπλοκ:

- Το τελευταίο μπλοκ ανώτατου επιπέδου δεν χρειάζεται να έχει ετικέτα κλεισίματος (το μπλοκ τελειώνει με το τέλος του εγγράφου). Αυτό απλοποιεί τη συγγραφή των προτύπων-παιδιών, τα οποία ένα πρωτογενές μπλοκ.

- Για μεγαλύτερη αναγνωσιμότητα, μπορείτε προαιρετικά να δώσετε ένα όνομα στην ετικέτα `{/block}`, για παράδειγμα `{/block footer}`. Ωστόσο, το όνομα πρέπει να ταιριάζει με το όνομα του μπλοκ. Σε μεγαλύτερα πρότυπα, αυτή η τεχνική σας βοηθά να βλέπετε ποιες ετικέτες μπλοκ κλείνουν.

- Δεν μπορείτε να ορίσετε απευθείας πολλαπλές ετικέτες μπλοκ με το ίδιο όνομα στο ίδιο πρότυπο. Αυτό όμως μπορεί να επιτευχθεί με τη χρήση [δυναμικών ονομάτων μπλοκ |#dynamic block names].

- Μπορείτε να χρησιμοποιήσετε [n:attributes |syntax#n:attributes] για να ορίσετε μπλοκ όπως `<h1 n:block=title>Welcome to my awesome homepage</h1>`

- Τα μπλοκ μπορούν επίσης να χρησιμοποιηθούν χωρίς ονόματα μόνο για την εφαρμογή των [φίλτρων |syntax#filters] στην έξοδο: `{block|strip} hello {/block}`


Οριζόντια επαναχρησιμοποίηση `{import}` .{toc: Horizontal Reuse}
================================================================

Η οριζόντια επαναχρησιμοποίηση είναι ο τρίτος μηχανισμός επαναχρησιμοποίησης και κληρονομικότητας στο Latte. Επιτρέπει τη φόρτωση μπλοκ από άλλα πρότυπα. Είναι παρόμοιο με τη δημιουργία ενός αρχείου με βοηθητικές συναρτήσεις στην PHP και στη συνέχεια τη φόρτωσή του χρησιμοποιώντας το `require`.

Ενώ η κληρονομικότητα διάταξης προτύπου είναι ένα από τα πιο ισχυρά χαρακτηριστικά του Latte, περιορίζεται στην απλή κληρονομικότητα - ένα πρότυπο μπορεί να επεκτείνει μόνο ένα άλλο πρότυπο. Η οριζόντια επαναχρησιμοποίηση είναι ένας τρόπος για την επίτευξη πολλαπλής κληρονομικότητας.

Ας έχουμε ένα σύνολο από ορισμούς μπλοκ:

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

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

Χρησιμοποιώντας την εντολή `{import}`, εισάγετε όλα τα μπλοκ και τους [ορισμούς |#definitions] που ορίζονται στο `blocks.latte` σε ένα άλλο πρότυπο:

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

{* Τα μπλοκ sidebar και menu μπορούν τώρα να χρησιμοποιηθούν *}
```

(π.χ. χρησιμοποιήστε την εντολή `{import}` στο `layout.latte`), τα μπλοκ θα είναι διαθέσιμα και σε όλα τα θυγατρικά πρότυπα, πράγμα πολύ βολικό.

Το πρότυπο που πρόκειται να εισαχθεί (π.χ. `blocks.latte`) δεν πρέπει να [επεκτείνει |#Layout Inheritance] άλλο πρότυπο, δηλαδή να χρησιμοποιήσετε το `{layout}`. Ωστόσο, μπορεί να εισάγει άλλα πρότυπα.

Η ετικέτα `{import}` πρέπει να είναι η πρώτη ετικέτα προτύπου μετά το `{layout}`. Το όνομα του προτύπου μπορεί να είναι οποιαδήποτε έκφραση PHP:

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

Μπορείτε να χρησιμοποιήσετε όσες δηλώσεις `{import}` θέλετε σε οποιοδήποτε συγκεκριμένο πρότυπο. Αν δύο εισαγόμενα πρότυπα ορίζουν το ίδιο μπλοκ, το πρώτο κερδίζει. Ωστόσο, η υψηλότερη προτεραιότητα δίνεται στο κύριο πρότυπο, το οποίο μπορεί να αντικαταστήσει οποιοδήποτε εισαγόμενο μπλοκ.

Το περιεχόμενο των μπλοκ που έχουν αντικατασταθεί μπορεί να διατηρηθεί με την εισαγωγή του μπλοκ με τον ίδιο τρόπο όπως ένα [γονικό μπλοκ |#parent block]:

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

{import 'blocks.latte'}

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

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

Σε αυτό το παράδειγμα, το `{include parent}` θα καλέσει σωστά το μπλοκ `sidebar` από το πρότυπο `blocks.latte`.


Κληρονομικότητα μονάδων `{embed}` .{toc: Unit Inheritance}
==========================================================

Η κληρονομικότητα μονάδας μεταφέρει την ιδέα της κληρονομικότητας διάταξης στο επίπεδο των τμημάτων περιεχομένου. Ενώ η κληρονομικότητα διάταξης λειτουργεί με "σκελετούς εγγράφων", οι οποίοι ζωντανεύουν από πρότυπα-παιδιά, η κληρονομικότητα μονάδων σας επιτρέπει να δημιουργείτε σκελετούς για μικρότερες μονάδες περιεχομένου και να τους επαναχρησιμοποιείτε οπουδήποτε θέλετε.

Στην κληρονομικότητα μονάδων η ετικέτα `{embed}` είναι το κλειδί. Συνδυάζει τη συμπεριφορά των `{include}` και `{layout}`. Σας επιτρέπει να συμπεριλάβετε τα περιεχόμενα ενός άλλου προτύπου ή μπλοκ και να περάσετε προαιρετικά μεταβλητές, όπως ακριβώς κάνει το `{include}`. Σας επιτρέπει επίσης να παρακάμψετε οποιοδήποτε μπλοκ που ορίζεται μέσα στο συμπεριλαμβανόμενο πρότυπο, όπως κάνει το `{layout}`.

Για παράδειγμα, θα χρησιμοποιήσουμε το πτυσσόμενο στοιχείο ακορντεόν. Ας ρίξουμε μια ματιά στον σκελετό του στοιχείου στο πρότυπο `collapsible.latte`:

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

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

Οι ετικέτες `{block}` ορίζουν δύο μπλοκ που μπορούν να συμπληρώσουν τα πρότυπα-παιδιά. Ναι, όπως και στην περίπτωση του προτύπου γονέα στο πρότυπο κληρονομικότητας διάταξης. Βλέπετε επίσης τη μεταβλητή `$modifierClass`.

Ας χρησιμοποιήσουμε το στοιχείο μας στο πρότυπο. Σε αυτό το σημείο έρχεται το `{embed}`. Είναι ένα εξαιρετικά ισχυρό κομμάτι του κιτ που μας επιτρέπει να κάνουμε όλα τα πράγματα: να συμπεριλάβουμε τα περιεχόμενα του προτύπου του στοιχείου, να προσθέσουμε μεταβλητές σε αυτό και να προσθέσουμε μπλοκ με προσαρμοσμένη HTML σε αυτό:

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

Η έξοδος μπορεί να μοιάζει κάπως έτσι:

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

Τα μπλοκ μέσα σε ετικέτες ενσωμάτωσης σχηματίζουν ένα ξεχωριστό επίπεδο, ανεξάρτητο από άλλα μπλοκ. Επομένως, μπορούν να έχουν το ίδιο όνομα με το μπλοκ που βρίσκεται έξω από την ενσωμάτωση και δεν επηρεάζονται με κανέναν τρόπο. Χρησιμοποιώντας την ετικέτα [include |#Printing Blocks] μέσα στις ετικέτες `{embed}` μπορείτε να εισάγετε μπλοκ που δημιουργήθηκαν εδώ, μπλοκ από το ενσωματωμένο πρότυπο (τα οποία *δεν* είναι [τοπικά |#Local Blocks]), καθώς και μπλοκ από το κύριο πρότυπο τα οποία *είναι* τοπικά. Μπορείτε επίσης να [εισάγετε μπλοκ |#Horizontal Reuse] από άλλα αρχεία:

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

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

	{block inner}…{/block}

	{block title}
		{include inner} {* λειτουργεί, το μπλοκ ορίζεται μέσα στην embed *}
		{include hello} {* λειτουργεί, το μπλοκ είναι τοπικό σε αυτό το πρότυπο *}
		{include content} {* λειτουργεί, το μπλοκ ορίζεται στο ενσωματωμένο πρότυπο *}
		{include aBlockDefinedInImportedTemplate} {* έργα *}
		{include outer} {* δεν λειτουργεί! - το μπλοκ βρίσκεται στο εξωτερικό στρώμα *}
	{/block}
{/embed}
```

Τα ενσωματωμένα πρότυπα δεν έχουν πρόσβαση στις μεταβλητές του ενεργού πλαισίου, αλλά έχουν πρόσβαση στις παγκόσμιες μεταβλητές.

Με το `{embed}` μπορείτε να εισάγετε όχι μόνο πρότυπα αλλά και άλλα μπλοκ, οπότε το προηγούμενο παράδειγμα θα μπορούσε να γραφτεί ως εξής:

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

Αν περάσουμε μια έκφραση στο `{embed}` και δεν είναι σαφές αν πρόκειται για μπλοκ ή για όνομα αρχείου, προσθέστε τη λέξη-κλειδί `block` ή `file`:

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


Περιπτώσεις χρήσης .[#toc-use-cases]
====================================

Υπάρχουν διάφοροι τύποι κληρονομικότητας και επαναχρησιμοποίησης κώδικα στο Latte. Ας συνοψίσουμε τις κύριες έννοιες για περισσότερη σαφήνεια:


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

**Περίπτωση χρήσης:** Χρήση των `header.latte` & `footer.latte` μέσα στο `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}`
----------

**Περίπτωση χρήσης**: Επέκταση του `layout.latte` μέσα στο `homepage.latte` & `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}`
----------

**Περίπτωση χρήσης**: `sidebar.latte` σε `single.product.latte` & `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}`
----------

**Περίπτωση χρήσης**: Μια συνάρτηση που παίρνει κάποιες μεταβλητές και εξάγει κάποια σήμανση.

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

**Περίπτωση χρήσης**: Ενσωμάτωση του `pagination.latte` στο `product.table.latte` & `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}
```

Κληρονομικότητα προτύπων και επαναχρησιμοποίηση

Οι μηχανισμοί επαναχρησιμοποίησης προτύπων και κληρονομικότητας είναι εδώ για να ενισχύσουν την παραγωγικότητά σας, επειδή κάθε πρότυπο περιέχει μόνο το μοναδικό του περιεχόμενο και τα επαναλαμβανόμενα στοιχεία και δομές επαναχρησιμοποιούνται. Παρουσιάζουμε τρεις έννοιες: κληρονομικότητα διάταξης, οριζόντια επαναχρησιμοποίηση και κληρονομικότητα μονάδων.

Η έννοια της κληρονομικότητας προτύπων Latte είναι παρόμοια με την κληρονομικότητα κλάσεων της PHP. Ορίζετε ένα πρότυπο γονέα από το οποίο άλλα πρότυπα-παιδιά μπορούν να επεκταθούν και να αντικαταστήσουν τμήματα του προτύπου γονέα. Λειτουργεί εξαιρετικά όταν τα στοιχεία μοιράζονται μια κοινή δομή. Ακούγεται περίπλοκο; Μην ανησυχείτε, δεν είναι.

Κληρονομικότητα διάταξης {layout}

Ας δούμε την κληρονομικότητα προτύπων διάταξης ξεκινώντας με ένα παράδειγμα. Πρόκειται για ένα πρότυπο γονέα το οποίο θα ονομάσουμε για παράδειγμα layout.latte και ορίζει ένα έγγραφο-σκελετό 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>

Οι ετικέτες {block} ορίζουν τρία μπλοκ που μπορούν να συμπληρώσουν τα πρότυπα-παιδιά. Το μόνο που κάνει η ετικέτα μπλοκ είναι να πει στη μηχανή προτύπων ότι ένα πρότυπο παιδί μπορεί να παρακάμψει αυτά τα τμήματα του προτύπου ορίζοντας το δικό του μπλοκ με το ίδιο όνομα.

Ένα υποκατάστατο πρότυπο μπορεί να μοιάζει ως εξής:

{layout 'layout.latte'}

{block title}My amazing blog{/block}

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

Η ετικέτα {layout} είναι το κλειδί εδώ. Λέει στη μηχανή προτύπων ότι αυτό το πρότυπο „επεκτείνει“ ένα άλλο πρότυπο. Όταν το Latte αποδίδει αυτό το πρότυπο, πρώτα εντοπίζει τον γονέα – σε αυτή την περίπτωση, το layout.latte.

Σε αυτό το σημείο, η μηχανή προτύπων θα παρατηρήσει τις τρεις ετικέτες μπλοκ στο layout.latte και θα αντικαταστήσει αυτά τα μπλοκ με τα περιεχόμενα του προτύπου-παιδί. Σημειώστε ότι εφόσον το πρότυπο παιδί δεν όρισε το μπλοκ footer, αντί αυτού χρησιμοποιείται το περιεχόμενο από το πρότυπο γονέα. Το περιεχόμενο μέσα σε μια ετικέτα {block} σε ένα γονικό πρότυπο χρησιμοποιείται πάντα ως εφεδρικό.

Η έξοδος μπορεί να μοιάζει ως εξής:

<!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>

Σε ένα πρότυπο παιδί, τα μπλοκ μπορούν να βρίσκονται μόνο είτε στο ανώτερο επίπεδο είτε μέσα σε ένα άλλο μπλοκ, δηλ:

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

Επίσης, ένα μπλοκ θα δημιουργείται πάντα στο ανεξάρτητα από το αν η συνθήκη που το περιβάλλει {if} αξιολογείται ως αληθής ή ψευδής. Σε αντίθεση με ό,τι μπορεί να νομίζετε, αυτό το πρότυπο ορίζει ένα μπλοκ.

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

Αν θέλετε η έξοδος μέσα στο μπλοκ να εμφανίζεται υπό συνθήκη, χρησιμοποιήστε αντ' αυτού τα ακόλουθα:

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

Τα δεδομένα έξω από ένα μπλοκ σε ένα πρότυπο παιδί εκτελούνται πριν από την απόδοση του προτύπου διάταξης, επομένως μπορείτε να το χρησιμοποιήσετε για να ορίσετε μεταβλητές όπως το {var $foo = bar} και να διαδώσετε δεδομένα σε ολόκληρη την αλυσίδα κληρονομικότητας:

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

...

Κληρονομικότητα πολλαπλών επιπέδων

Μπορείτε να χρησιμοποιήσετε όσα επίπεδα κληρονομικότητας χρειάζεστε. Ένας συνηθισμένος τρόπος χρήσης της κληρονομικότητας διάταξης είναι η ακόλουθη προσέγγιση τριών επιπέδων:

  1. Δημιουργήστε ένα πρότυπο layout.latte που κρατάει την κύρια εμφάνιση και αίσθηση του ιστότοπού σας.
  2. Δημιουργήστε ένα πρότυπο layout-SECTIONNAME.latte για κάθε τμήμα του ιστότοπού σας. Για παράδειγμα, layout-news.latte, layout-blog.latte κ.λπ. Όλα αυτά τα πρότυπα επεκτείνουν το layout.latte και περιλαμβάνουν στυλ/σχεδιασμό για κάθε τμήμα.
  3. Δημιουργήστε μεμονωμένα πρότυπα για κάθε τύπο σελίδας, όπως ένα άρθρο ειδήσεων ή μια καταχώρηση σε ιστολόγιο. Αυτά τα πρότυπα επεκτείνουν το κατάλληλο πρότυπο τμήματος.

Κληρονομικότητα δυναμικής διάταξης

Μπορείτε να χρησιμοποιήσετε μια μεταβλητή ή οποιαδήποτε έκφραση PHP ως όνομα του προτύπου γονέα, ώστε η κληρονομικότητα να συμπεριφέρεται δυναμικά:

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

Μπορείτε επίσης να χρησιμοποιήσετε το API Latte για να επιλέξετε αυτόματα το πρότυπο διάταξης.

Συμβουλές

Ακολουθούν ορισμένες συμβουλές για την εργασία με την κληρονομικότητα διάταξης:

  • Εάν χρησιμοποιείτε το {layout} σε ένα πρότυπο, πρέπει να είναι η πρώτη ετικέτα προτύπου σε αυτό το πρότυπο.
  • Η διάταξη μπορεί να αναζητηθεί αυτόματα (όπως στους παρουσιαστές). Σε αυτή την περίπτωση, αν το πρότυπο δεν πρέπει να έχει διάταξη, θα το υποδείξει με την ετικέτα {layout none}.
  • Η ετικέτα {layout} έχει ψευδώνυμο {extends}.
  • Το όνομα αρχείου του εκτεταμένου προτύπου εξαρτάται από τον φορτωτή προτύπων.
  • Μπορείτε να έχετε όσα μπλοκ θέλετε. Θυμηθείτε, τα υποδείγματα-παιδιά δεν χρειάζεται να ορίζουν όλα τα μπλοκ γονέων, οπότε μπορείτε να συμπληρώσετε λογικές προεπιλογές σε πολλά μπλοκ και στη συνέχεια να ορίσετε μόνο αυτά που χρειάζεστε αργότερα.

Μπλοκ {block}

Βλέπε επίσης ανώνυμο {block}

Ένα μπλοκ παρέχει έναν τρόπο να αλλάξετε τον τρόπο απόδοσης ενός συγκεκριμένου τμήματος ενός προτύπου, αλλά δεν παρεμβαίνει με κανέναν τρόπο στη λογική γύρω από αυτό. Ας πάρουμε το παρακάτω παράδειγμα για να δείξουμε πώς λειτουργεί ένα μπλοκ και κυρίως πώς δεν λειτουργεί:

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

Αν αποδώσετε αυτό το πρότυπο, το αποτέλεσμα θα είναι ακριβώς το ίδιο με ή χωρίς τις ετικέτες μπλοκ. Τα μπλοκ έχουν πρόσβαση σε μεταβλητές από εξωτερικά πεδία εφαρμογής. Είναι απλώς ένας τρόπος για να το κάνετε να μπορεί να παρακαμφθεί από ένα πρότυπο-παιδί:

{layout 'parent.Latte'}

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

Τώρα, κατά την απόδοση του παιδικού προτύπου, ο βρόχος θα χρησιμοποιήσει το μπλοκ που ορίζεται στο παιδικό πρότυπο child.Latte αντί για αυτό που ορίζεται στο βασικό parent.Latte; το εκτελούμενο πρότυπο είναι τότε ισοδύναμο με το ακόλουθο:

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

Ωστόσο, αν δημιουργήσουμε μια νέα μεταβλητή μέσα σε ένα μπλοκ με όνομα ή αντικαταστήσουμε μια τιμή μιας υπάρχουσας, η αλλαγή θα είναι ορατή μόνο μέσα στο μπλοκ:

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

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

Τα περιεχόμενα του μπλοκ μπορούν να τροποποιηθούν από φίλτρα. Το ακόλουθο παράδειγμα αφαιρεί όλη την HTML και την αλλαγή τίτλου:

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

Η ετικέτα μπορεί επίσης να γραφτεί ως n:attribute:

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

Τοπικά μπλοκ

Κάθε μπλοκ παρακάμπτει το περιεχόμενο του γονικού μπλοκ με το ίδιο όνομα. Εκτός από τα τοπικά μπλοκ. Είναι κάτι σαν τις ιδιωτικές μεθόδους της κλάσης. Μπορείτε να δημιουργήσετε ένα πρότυπο χωρίς να ανησυχείτε ότι – λόγω σύμπτωσης των ονομάτων των μπλοκ – θα αντικατασταθούν από το δεύτερο πρότυπο.

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

Εκτύπωση μπλοκ {include}

Βλέπε επίσης {include file}

Για να εκτυπώσετε ένα μπλοκ σε ένα συγκεκριμένο σημείο, χρησιμοποιήστε την ετικέτα {include blockname}:

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

<h1>{include title}</h1>

Μπορείτε επίσης να εμφανίσετε μπλοκ από άλλο πρότυπο:

{include footer from 'main.latte'}

εκτός αν το μπλοκ έχει οριστεί στο ίδιο αρχείο όπου περιλαμβάνεται. Ωστόσο, έχουν πρόσβαση στις παγκόσμιες μεταβλητές.

Μπορείτε να περάσετε μεταβλητές στο μπλοκ με τον ακόλουθο τρόπο:

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

Μπορείτε να χρησιμοποιήσετε μια μεταβλητή ή οποιαδήποτε έκφραση στην PHP ως όνομα μπλοκ. Σε αυτή την περίπτωση, προσθέστε τη λέξη-κλειδί block πριν από τη μεταβλητή, ώστε να είναι γνωστό κατά τη μεταγλώττιση ότι πρόκειται για μπλοκ και όχι για insert template, το όνομα του οποίου θα μπορούσε επίσης να βρίσκεται στη μεταβλητή:

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

Το μπλοκ μπορεί επίσης να εκτυπωθεί μέσα στον εαυτό του, κάτι που είναι χρήσιμο, για παράδειγμα, κατά την απόδοση μιας δενδρικής δομής:

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

Αντί του {include menu, ...} μπορούμε επίσης να γράψουμε {include this, ...} όπου this σημαίνει τρέχον μπλοκ.

Το εκτυπωμένο περιεχόμενο μπορεί να τροποποιηθεί με φίλτρα. Το ακόλουθο παράδειγμα αφαιρεί όλη την HTML και την αλλαγή του τίτλου:

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

Γονικό μπλοκ

Εάν πρέπει να εκτυπώσετε το περιεχόμενο του μπλοκ από το γονικό πρότυπο, η δήλωση {include parent} θα κάνει το κόλπο. Αυτό είναι χρήσιμο αν θέλετε να προσθέσετε στα περιεχόμενα ενός γονικού μπλοκ αντί να το παρακάμψετε πλήρως.

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

Ορισμοί {define}

Εκτός από τα μπλοκ, υπάρχουν επίσης „ορισμοί“ στο Latte. Είναι συγκρίσιμοι με τις συναρτήσεις στις κανονικές γλώσσες προγραμματισμού. Είναι χρήσιμοι για την επαναχρησιμοποίηση τμημάτων προτύπων για να μην επαναλαμβάνεστε.

Η Latte προσπαθεί να κρατήσει τα πράγματα απλά, οπότε βασικά οι ορισμοί είναι το ίδιο με τα μπλοκ, και ό,τι λέγεται για τα μπλοκ ισχύει και για τους ορισμούς. Διαφέρουν από τα μπλοκ σε αυτό:

  1. περικλείονται σε ετικέτες {define}
  2. αποδίδονται μόνο όταν εισάγονται μέσω {include}
  3. μπορείτε να ορίσετε παραμέτρους για αυτά όπως οι συναρτήσεις στην PHP
{block foo}<p>Hello</p>{/block}
{* prints: <p>Hello</p> *}

{define bar}<p>World</p>{/define}
{* δεν εκτυπώνει τίποτα *}

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

Φανταστείτε ότι έχετε ένα βοηθητικό πρότυπο με μια συλλογή ορισμών για το πώς να σχεδιάζετε φόρμες 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}

Τα επιχειρήματα ενός ορισμού είναι πάντοτε προαιρετικά με προεπιλεγμένη τιμή null, εκτός εάν έχει καθοριστεί προεπιλεγμένη τιμή (εδώ 'text' είναι η προεπιλεγμένη τιμή για το $type). Οι τύποι παραμέτρων μπορούν επίσης να δηλωθούν: {define input, string $name, ...}.

Το πρότυπο με τους ορισμούς φορτώνεται χρησιμοποιώντας {import}. Οι ίδιοι οι ορισμοί απεικονίζονται με τον ίδιο τρόπο όπως και τα μπλοκ:

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

Οι ορισμοί δεν έχουν πρόσβαση στις μεταβλητές του ενεργού πλαισίου, αλλά έχουν πρόσβαση σε παγκόσμιες μεταβλητές.

Δυναμικά ονόματα μπλοκ

Η Latte επιτρέπει μεγάλη ευελιξία στον ορισμό των μπλοκ, επειδή το όνομα του μπλοκ μπορεί να είναι οποιαδήποτε έκφραση της PHP. Αυτό το παράδειγμα ορίζει τρία μπλοκ με τα ονόματα hi-Peter, hi-John και hi-Mary:

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

Για παράδειγμα, μπορούμε να επαναπροσδιορίσουμε μόνο ένα μπλοκ σε ένα πρότυπο παιδί:

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

Έτσι, η έξοδος θα μοιάζει με αυτό:

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

Έλεγχος ύπαρξης μπλοκ {ifset}

Βλέπε επίσης {ifset $var}

Χρησιμοποιήστε τη δοκιμή {ifset blockname} για να ελέγξετε αν ένα μπλοκ (ή περισσότερα μπλοκ) υπάρχει στο τρέχον πλαίσιο:

{ifset footer}
	...
{/ifset}

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

Μπορείτε να χρησιμοποιήσετε μια μεταβλητή ή οποιαδήποτε έκφραση στην PHP ως όνομα μπλοκ. Σε αυτή την περίπτωση, προσθέστε τη λέξη-κλειδί block πριν από τη μεταβλητή για να καταστήσετε σαφές ότι δεν είναι η μεταβλητή που ελέγχεται:

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

Η ύπαρξη μπλοκ επιστρέφεται επίσης από τη συνάρτηση hasBlock():

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

Συμβουλές

Ακολουθούν μερικές συμβουλές για την εργασία με μπλοκ:

  • Το τελευταίο μπλοκ ανώτατου επιπέδου δεν χρειάζεται να έχει ετικέτα κλεισίματος (το μπλοκ τελειώνει με το τέλος του εγγράφου). Αυτό απλοποιεί τη συγγραφή των προτύπων-παιδιών, τα οποία ένα πρωτογενές μπλοκ.
  • Για μεγαλύτερη αναγνωσιμότητα, μπορείτε προαιρετικά να δώσετε ένα όνομα στην ετικέτα {/block}, για παράδειγμα {/block footer}. Ωστόσο, το όνομα πρέπει να ταιριάζει με το όνομα του μπλοκ. Σε μεγαλύτερα πρότυπα, αυτή η τεχνική σας βοηθά να βλέπετε ποιες ετικέτες μπλοκ κλείνουν.
  • Δεν μπορείτε να ορίσετε απευθείας πολλαπλές ετικέτες μπλοκ με το ίδιο όνομα στο ίδιο πρότυπο. Αυτό όμως μπορεί να επιτευχθεί με τη χρήση δυναμικών ονομάτων μπλοκ.
  • Μπορείτε να χρησιμοποιήσετε n:attributes για να ορίσετε μπλοκ όπως <h1 n:block=title>Welcome to my awesome homepage</h1>
  • Τα μπλοκ μπορούν επίσης να χρησιμοποιηθούν χωρίς ονόματα μόνο για την εφαρμογή των φίλτρων στην έξοδο: {block|strip} hello {/block}

Οριζόντια επαναχρησιμοποίηση {import}

Η οριζόντια επαναχρησιμοποίηση είναι ο τρίτος μηχανισμός επαναχρησιμοποίησης και κληρονομικότητας στο Latte. Επιτρέπει τη φόρτωση μπλοκ από άλλα πρότυπα. Είναι παρόμοιο με τη δημιουργία ενός αρχείου με βοηθητικές συναρτήσεις στην PHP και στη συνέχεια τη φόρτωσή του χρησιμοποιώντας το require.

Ενώ η κληρονομικότητα διάταξης προτύπου είναι ένα από τα πιο ισχυρά χαρακτηριστικά του Latte, περιορίζεται στην απλή κληρονομικότητα – ένα πρότυπο μπορεί να επεκτείνει μόνο ένα άλλο πρότυπο. Η οριζόντια επαναχρησιμοποίηση είναι ένας τρόπος για την επίτευξη πολλαπλής κληρονομικότητας.

Ας έχουμε ένα σύνολο από ορισμούς μπλοκ:

{block sidebar}...{/block}

{block menu}...{/block}

Χρησιμοποιώντας την εντολή {import}, εισάγετε όλα τα μπλοκ και τους ορισμούς που ορίζονται στο blocks.latte σε ένα άλλο πρότυπο:

{import 'blocks.latte'}

{* Τα μπλοκ sidebar και menu μπορούν τώρα να χρησιμοποιηθούν *}

(π.χ. χρησιμοποιήστε την εντολή {import} στο layout.latte), τα μπλοκ θα είναι διαθέσιμα και σε όλα τα θυγατρικά πρότυπα, πράγμα πολύ βολικό.

Το πρότυπο που πρόκειται να εισαχθεί (π.χ. blocks.latte) δεν πρέπει να επεκτείνει άλλο πρότυπο, δηλαδή να χρησιμοποιήσετε το {layout}. Ωστόσο, μπορεί να εισάγει άλλα πρότυπα.

Η ετικέτα {import} πρέπει να είναι η πρώτη ετικέτα προτύπου μετά το {layout}. Το όνομα του προτύπου μπορεί να είναι οποιαδήποτε έκφραση PHP:

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

Μπορείτε να χρησιμοποιήσετε όσες δηλώσεις {import} θέλετε σε οποιοδήποτε συγκεκριμένο πρότυπο. Αν δύο εισαγόμενα πρότυπα ορίζουν το ίδιο μπλοκ, το πρώτο κερδίζει. Ωστόσο, η υψηλότερη προτεραιότητα δίνεται στο κύριο πρότυπο, το οποίο μπορεί να αντικαταστήσει οποιοδήποτε εισαγόμενο μπλοκ.

Το περιεχόμενο των μπλοκ που έχουν αντικατασταθεί μπορεί να διατηρηθεί με την εισαγωγή του μπλοκ με τον ίδιο τρόπο όπως ένα γονικό μπλοκ:

{layout 'layout.latte'}

{import 'blocks.latte'}

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

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

Σε αυτό το παράδειγμα, το {include parent} θα καλέσει σωστά το μπλοκ sidebar από το πρότυπο blocks.latte.

Κληρονομικότητα μονάδων {embed}

Η κληρονομικότητα μονάδας μεταφέρει την ιδέα της κληρονομικότητας διάταξης στο επίπεδο των τμημάτων περιεχομένου. Ενώ η κληρονομικότητα διάταξης λειτουργεί με „σκελετούς εγγράφων“, οι οποίοι ζωντανεύουν από πρότυπα-παιδιά, η κληρονομικότητα μονάδων σας επιτρέπει να δημιουργείτε σκελετούς για μικρότερες μονάδες περιεχομένου και να τους επαναχρησιμοποιείτε οπουδήποτε θέλετε.

Στην κληρονομικότητα μονάδων η ετικέτα {embed} είναι το κλειδί. Συνδυάζει τη συμπεριφορά των {include} και {layout}. Σας επιτρέπει να συμπεριλάβετε τα περιεχόμενα ενός άλλου προτύπου ή μπλοκ και να περάσετε προαιρετικά μεταβλητές, όπως ακριβώς κάνει το {include}. Σας επιτρέπει επίσης να παρακάμψετε οποιοδήποτε μπλοκ που ορίζεται μέσα στο συμπεριλαμβανόμενο πρότυπο, όπως κάνει το {layout}.

Για παράδειγμα, θα χρησιμοποιήσουμε το πτυσσόμενο στοιχείο ακορντεόν. Ας ρίξουμε μια ματιά στον σκελετό του στοιχείου στο πρότυπο collapsible.latte:

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

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

Οι ετικέτες {block} ορίζουν δύο μπλοκ που μπορούν να συμπληρώσουν τα πρότυπα-παιδιά. Ναι, όπως και στην περίπτωση του προτύπου γονέα στο πρότυπο κληρονομικότητας διάταξης. Βλέπετε επίσης τη μεταβλητή $modifierClass.

Ας χρησιμοποιήσουμε το στοιχείο μας στο πρότυπο. Σε αυτό το σημείο έρχεται το {embed}. Είναι ένα εξαιρετικά ισχυρό κομμάτι του κιτ που μας επιτρέπει να κάνουμε όλα τα πράγματα: να συμπεριλάβουμε τα περιεχόμενα του προτύπου του στοιχείου, να προσθέσουμε μεταβλητές σε αυτό και να προσθέσουμε μπλοκ με προσαρμοσμένη HTML σε αυτό:

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

Η έξοδος μπορεί να μοιάζει κάπως έτσι:

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

Τα μπλοκ μέσα σε ετικέτες ενσωμάτωσης σχηματίζουν ένα ξεχωριστό επίπεδο, ανεξάρτητο από άλλα μπλοκ. Επομένως, μπορούν να έχουν το ίδιο όνομα με το μπλοκ που βρίσκεται έξω από την ενσωμάτωση και δεν επηρεάζονται με κανέναν τρόπο. Χρησιμοποιώντας την ετικέτα include μέσα στις ετικέτες {embed} μπορείτε να εισάγετε μπλοκ που δημιουργήθηκαν εδώ, μπλοκ από το ενσωματωμένο πρότυπο (τα οποία δεν είναι τοπικά), καθώς και μπλοκ από το κύριο πρότυπο τα οποία είναι τοπικά. Μπορείτε επίσης να εισάγετε μπλοκ από άλλα αρχεία:

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

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

	{block inner}…{/block}

	{block title}
		{include inner} {* λειτουργεί, το μπλοκ ορίζεται μέσα στην embed *}
		{include hello} {* λειτουργεί, το μπλοκ είναι τοπικό σε αυτό το πρότυπο *}
		{include content} {* λειτουργεί, το μπλοκ ορίζεται στο ενσωματωμένο πρότυπο *}
		{include aBlockDefinedInImportedTemplate} {* έργα *}
		{include outer} {* δεν λειτουργεί! - το μπλοκ βρίσκεται στο εξωτερικό στρώμα *}
	{/block}
{/embed}

Τα ενσωματωμένα πρότυπα δεν έχουν πρόσβαση στις μεταβλητές του ενεργού πλαισίου, αλλά έχουν πρόσβαση στις παγκόσμιες μεταβλητές.

Με το {embed} μπορείτε να εισάγετε όχι μόνο πρότυπα αλλά και άλλα μπλοκ, οπότε το προηγούμενο παράδειγμα θα μπορούσε να γραφτεί ως εξής:

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

Αν περάσουμε μια έκφραση στο {embed} και δεν είναι σαφές αν πρόκειται για μπλοκ ή για όνομα αρχείου, προσθέστε τη λέξη-κλειδί block ή file:

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

Περιπτώσεις χρήσης

Υπάρχουν διάφοροι τύποι κληρονομικότητας και επαναχρησιμοποίησης κώδικα στο Latte. Ας συνοψίσουμε τις κύριες έννοιες για περισσότερη σαφήνεια:

{include template}

Περίπτωση χρήσης: Χρήση των header.latte & footer.latte μέσα στο 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}

Περίπτωση χρήσης: Επέκταση του layout.latte μέσα στο homepage.latte & 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}

Περίπτωση χρήσης: sidebar.latte σε single.product.latte & 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}

Περίπτωση χρήσης: Μια συνάρτηση που παίρνει κάποιες μεταβλητές και εξάγει κάποια σήμανση.

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}

Περίπτωση χρήσης: Ενσωμάτωση του pagination.latte στο product.table.latte & 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}