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

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

Η έννοια της κληρονομικότητας προτύπων 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>

Τα tags {block} ορίζουν τρία μπλοκ που μπορούν να συμπληρώσουν τα θυγατρικά πρότυπα. Το tag block απλώς δηλώνει ότι αυτή η θέση μπορεί να αντικατασταθεί από ένα θυγατρικό πρότυπο ορίζοντας το δικό του μπλοκ με το ίδιο όνομα.

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

{layout 'layout.latte'}

{block title}My amazing blog{/block}

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

Το κλειδί εδώ είναι το tag {layout}. Λέει στο Latte ότι αυτό το πρότυπο “επεκτείνει” ένα άλλο πρότυπο. Όταν το Latte αποδίδει αυτό το πρότυπο, βρίσκει πρώτα το γονικό πρότυπο – σε αυτή την περίπτωση layout.latte.

Σε αυτό το σημείο, το Latte παρατηρεί τα τρία tags μπλοκ στο layout.latte και αντικαθιστά αυτά τα μπλοκ με το περιεχόμενο του θυγατρικού προτύπου. Δεδομένου ότι το θυγατρικό πρότυπο δεν όρισε το μπλοκ footer, χρησιμοποιείται αντ' αυτού το περιεχόμενο από το γονικό πρότυπο. Το περιεχόμενο εντός του tag {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'}

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

Συμβουλές

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

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

Μπλοκ {block}

Δείτε επίσης το ανώνυμο {block}

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

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

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

{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}                  // εκτυπώνει: foo
bar: {$bar ?? 'not defined'} // εκτυπώνει: not defined

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

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

Το tag μπορεί επίσης να γραφτεί ως n:attribute:

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

Τοπικά μπλοκ

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

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

Απόδοση μπλοκ {include}

Δείτε επίσης {include file}

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

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

<h1>{include title}</h1>

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

{include footer from 'main.latte'}

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

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

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

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

{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. περικλείονται σε tags {define}
  2. αποδίδονται μόνο όταν τους ενσωματώνετε μέσω {include}
  3. μπορούν να τους οριστούν παράμετροι παρόμοια με τις συναρτήσεις στην PHP
{block foo}<p>Hello</p>{/block}
{* εκτυπώνει: <p>Hello</p> *}

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

{include bar}
{* εκτυπώνει: <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>

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

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

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

{foreach [Peter, John, Mary] as $name}
	{block "hi-$name"}Γεια, είμαι ο {$name}.{/block}
{/foreach}

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

{block hi-John}Γεια. Είμαι ο {$name}.{/block}

Έτσι, η έξοδος θα μοιάζει κάπως έτσι:

Γεια, είμαι ο Peter.
Γεια. Είμαι ο John.
Γεια, είμαι η Mary.

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

Δείτε επίσης {ifset $var}

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

{ifset footer}
	...
{/ifset}

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

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

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

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

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

Συμβουλές

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

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

Το tag {import} πρέπει να είναι το πρώτο tag προτύπου μετά το {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}

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

Στην κληρονομικότητα μονάδας, το κλειδί είναι το tag {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>

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

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

{embed 'collapsible.latte', modifierClass: my-style}
	{block title}
		Γεια σου Κόσμε
	{/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">
		Γεια σου Κόσμε
	</h4>

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

Τα μπλοκ μέσα στα ενσωματωμένα tags σχηματίζουν ένα ξεχωριστό επίπεδο ανεξάρτητο από τα άλλα μπλοκ. Επομένως, μπορούν να έχουν το ίδιο όνομα με ένα μπλοκ εκτός της ενσωμάτωσης και δεν επηρεάζονται καθόλου. Χρησιμοποιώντας το tag include μέσα στα tags {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}

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

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

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


{embed collapsible, modifierClass: my-style}
	{block title}
		Γεια σου Κόσμε
	{/block}
	...
{/embed}

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

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

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

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

{include template}

Περίπτωση χρήσης: Χρήση των header.latte και footer.latte μέσα στο layout.latte.

header.latte

<nav>
   <div>Αρχική</div>
   <div>Σχετικά</div>
</nav>

footer.latte

<footer>
   <div>Πνευματικά δικαιώματα</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>Αρχική σελίδα</p>
{/block}

about.latte

{layout 'layout.latte'}

{block main}
	<p>Σελίδα σχετικά</p>
{/block}

{import}

Περίπτωση χρήσης: sidebar.latte στα single.product.latte και single.service.latte.

sidebar.latte

{block sidebar}<aside>Αυτή είναι η πλαϊνή μπάρα</aside>{/block}

single.product.latte

{layout 'product.layout.latte'}

{import 'sidebar.latte'}

{block main}<main>Σελίδα προϊόντος</main>{/block}

single.service.latte

{layout 'service.layout.latte'}

{import 'sidebar.latte'}

{block main}<main>Σελίδα υπηρεσίας</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}</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}Πρώτη σελίδα προϊόντος{/block}
	{block last}Τελευταία σελίδα προϊόντος{/block}
{/embed}

service.table.latte

{embed 'pagination.latte', min: 1, max: $services->count}
	{block first}Πρώτη σελίδα υπηρεσίας{/block}
	{block last}Τελευταία σελίδα υπηρεσίας{/block}
{/embed}
έκδοση: 3.0