Επεκτείνοντας το Latte
Το Latte σχεδιάστηκε με γνώμονα την επεκτασιμότητα. Αν και το τυπικό σύνολο των tags, φίλτρων και συναρτήσεων καλύπτει πολλές περιπτώσεις χρήσης, συχνά χρειάζεται να προσθέσετε τη δική σας συγκεκριμένη λογική ή βοηθητικά εργαλεία. Αυτή η σελίδα παρέχει μια επισκόπηση των τρόπων επέκτασης του Latte ώστε να ταιριάζει απόλυτα στις απαιτήσεις του έργου σας – από απλούς βοηθούς έως σύνθετη νέα σύνταξη.
Τρόποι επέκτασης του Latte
Ακολουθεί μια γρήγορη επισκόπηση των κύριων τρόπων με τους οποίους μπορείτε να προσαρμόσετε και να επεκτείνετε το Latte:
- Προσαρμοσμένα φίλτρα: Για
μορφοποίηση ή μετασχηματισμό δεδομένων απευθείας στην έξοδο του
προτύπου (π.χ.
{$var|myFilter}
). Ιδανικό για εργασίες όπως μορφοποίηση ημερομηνιών, επεξεργασία κειμένου ή εφαρμογή συγκεκριμένου escaping. Μπορείτε επίσης να τα χρησιμοποιήσετε για να τροποποιήσετε μεγαλύτερα μπλοκ περιεχομένου HTML, περικλείοντας το περιεχόμενο σε ένα ανώνυμο{block}
και εφαρμόζοντας ένα προσαρμοσμένο φίλτρο σε αυτό. - Προσαρμοσμένες συναρτήσεις: Για
την προσθήκη επαναχρησιμοποιήσιμης λογικής που μπορεί να κληθεί μέσα
σε εκφράσεις στο πρότυπο (π.χ.
{myFunction($arg1, $arg2)}
). Χρήσιμο για υπολογισμούς, πρόσβαση σε βοηθητικές συναρτήσεις της εφαρμογής ή δημιουργία μικρών τμημάτων περιεχομένου. - Προσαρμοσμένα tags: Για τη δημιουργία
εντελώς νέων γλωσσικών κατασκευών (
{mytag}...{/mytag}
ήn:mytag
). Τα tags προσφέρουν τις περισσότερες δυνατότητες, επιτρέποντας τον ορισμό προσαρμοσμένων δομών, τον έλεγχο της ανάλυσης του προτύπου και την υλοποίηση σύνθετης λογικής απόδοσης. - Compilation Passes: Συναρτήσεις που τροποποιούν το αφηρημένο συντακτικό δέντρο (AST) του προτύπου μετά την ανάλυση, αλλά πριν από τη δημιουργία του κώδικα PHP. Χρησιμοποιούνται για προηγμένες βελτιστοποιήσεις, ελέγχους ασφαλείας (όπως το Sandbox) ή αυτόματες τροποποιήσεις κώδικα.
- Προσαρμοσμένοι loaders: Για την αλλαγή του τρόπου με τον οποίο το Latte αναζητά και φορτώνει αρχεία προτύπου (π.χ. φόρτωση από βάση δεδομένων, κρυπτογραφημένο αποθηκευτικό χώρο κ.λπ.).
Η επιλογή της σωστής μεθόδου επέκτασης είναι κρίσιμη. Πριν δημιουργήσετε ένα σύνθετο tag, σκεφτείτε αν ένα απλούστερο φίλτρο ή συνάρτηση θα ήταν αρκετό. Ας το δούμε με ένα παράδειγμα: υλοποίηση μιας γεννήτριας Lorem ipsum που δέχεται ως όρισμα τον αριθμό των λέξεων προς δημιουργία.
- Ως tag;
{lipsum 40}
– Πιθανό, αλλά τα tags είναι πιο κατάλληλα για δομές ελέγχου ή για τη δημιουργία σύνθετων tags. Τα tags δεν μπορούν να χρησιμοποιηθούν απευθείας σε εκφράσεις. - Ως φίλτρο;
{=40|lipsum}
– Τεχνικά λειτουργεί, αλλά τα φίλτρα προορίζονται για μετασχηματισμό της τιμής εισόδου. Εδώ, το40
είναι ένα όρισμα, όχι μια τιμή που μετασχηματίζεται. Αυτό φαίνεται σημασιολογικά λανθασμένο. - Ως συνάρτηση;
{lipsum(40)}
– Αυτή είναι η πιο φυσική λύση! Οι συναρτήσεις δέχονται ορίσματα και επιστρέφουν τιμές, κάτι που είναι ιδανικό για χρήση σε οποιαδήποτε έκφραση:{var $text = lipsum(40)}
.
Γενική σύσταση: Χρησιμοποιήστε συναρτήσεις για υπολογισμούς/δημιουργία, φίλτρα για μετασχηματισμό και tags για νέες γλωσσικές κατασκευές ή σύνθετα tags. Χρησιμοποιήστε τα περάσματα για χειρισμό του AST και τους loaders για την ανάκτηση των προτύπων.
Άμεση εγγραφή
Για βοηθητικά εργαλεία ειδικά για το έργο ή γρήγορες επεκτάσεις, το
Latte επιτρέπει την άμεση εγγραφή φίλτρων και συναρτήσεων στο
αντικείμενο Latte\Engine
.
Για να εγγράψετε ένα φίλτρο, χρησιμοποιήστε τη μέθοδο addFilter()
.
Το πρώτο όρισμα της συνάρτησης φίλτρου σας θα είναι η τιμή πριν από τον
χαρακτήρα |
και τα επόμενα ορίσματα είναι αυτά που περνούν μετά
την άνω και κάτω τελεία :
.
$latte = new Latte\Engine;
// Ορισμός φίλτρου (callable: συνάρτηση, στατική μέθοδος κ.λπ.)
$myTruncate = fn(string $s, int $length = 50) => mb_substr($s, 0, $length);
// Εγγραφή
$latte->addFilter('truncate', $myTruncate);
// Χρήση στο πρότυπο: {$text|truncate} ή {$text|truncate:100}
Μπορείτε επίσης να εγγράψετε έναν Filter Loader, μια συνάρτηση που παρέχει δυναμικά callables φίλτρων με βάση το ζητούμενο όνομα:
$latte->addFilterLoader(fn(string $name) => /* επιστρέφει ένα callable ή null */);
Για να εγγράψετε μια συνάρτηση που μπορεί να χρησιμοποιηθεί σε
εκφράσεις του προτύπου, χρησιμοποιήστε το addFunction()
.
$latte = new Latte\Engine;
// Ορισμός συνάρτησης
$isWeekend = fn(DateTimeInterface $date) => $date->format('N') >= 6;
// Εγγραφή
$latte->addFunction('isWeekend', $isWeekend);
// Χρήση στο πρότυπο: {if isWeekend($myDate)}Σαββατοκύριακο!{/if}
Περισσότερες πληροφορίες θα βρείτε στην ενότητα Δημιουργία προσαρμοσμένων φίλτρων και Συναρτήσεων.
Στιβαρός τρόπος: Latte Extension
Ενώ η άμεση εγγραφή είναι απλή, ο τυπικός και συνιστώμενος τρόπος για τη συσκευασία και διανομή επεκτάσεων Latte είναι μέσω των κλάσεων Extension. Ένα Extension χρησιμεύει ως κεντρικό σημείο διαμόρφωσης για την εγγραφή πολλαπλών tags, φίλτρων, συναρτήσεων, compiler passes και άλλων στοιχείων.
Γιατί να χρησιμοποιήσετε Extensions;
- Οργάνωση: Διατηρεί σχετικές επεκτάσεις (tags, φίλτρα κ.λπ. για μια συγκεκριμένη λειτουργία) μαζί σε μία κλάση.
- Επαναχρησιμοποίηση και κοινή χρήση: Συσκευάστε εύκολα τις επεκτάσεις σας για χρήση σε άλλα έργα ή για κοινή χρήση με την κοινότητα (π.χ. μέσω Composer).
- Πλήρης ισχύς: Τα προσαρμοσμένα tags και τα compiler passes μπορούν να εγγραφούν μόνο μέσω Extensions.
Εγγραφή ενός Extension
Ένα Extension εγγράφεται στο Latte χρησιμοποιώντας τη μέθοδο addExtension()
(ή μέσω του αρχείου
διαμόρφωσης):
$latte = new Latte\Engine;
$latte->addExtension(new MyProjectExtension);
Εάν εγγράψετε πολλαπλές επεκτάσεις και αυτές ορίζουν tags, φίλτρα ή συναρτήσεις με το ίδιο όνομα, υπερισχύει η τελευταία προστιθέμενη επέκταση. Αυτό σημαίνει επίσης ότι οι επεκτάσεις σας μπορούν να αντικαταστήσουν τα εγγενή tags/φίλτρα/συναρτήσεις.
Κάθε φορά που κάνετε μια αλλαγή στην κλάση και η αυτόματη ανανέωση δεν είναι απενεργοποιημένη, το Latte θα μεταγλωττίσει αυτόματα τα πρότυπά σας.
Δημιουργία ενός Extension
Για να δημιουργήσετε τη δική σας επέκταση, πρέπει να δημιουργήσετε μια κλάση που κληρονομεί από την Latte\Extension. Για να πάρετε μια ιδέα για το πώς μοιάζει μια τέτοια επέκταση, δείτε την ενσωματωμένη CoreExtension.
Ας δούμε τις μεθόδους που μπορείτε να υλοποιήσετε:
beforeCompile (Latte\Engine $engine): void
Καλείται πριν από τη μεταγλώττιση του προτύπου. Η μέθοδος μπορεί να χρησιμοποιηθεί, για παράδειγμα, για αρχικοποιήσεις που σχετίζονται με τη μεταγλώττιση.
getTags(): array
Καλείται κατά τη μεταγλώττιση του προτύπου. Επιστρέφει έναν συσχετιστικό πίνακα όνομα tag ⇒ callable, που είναι συναρτήσεις για την ανάλυση των tags. Περισσότερες πληροφορίες.
public function getTags(): array
{
return [
'foo' => FooNode::create(...),
'bar' => BarNode::create(...),
'n:baz' => NBazNode::create(...),
// ...
];
}
Το tag n:baz
αντιπροσωπεύει ένα καθαρό n:attribute, δηλαδή ένα tag που μπορεί να
γραφτεί μόνο ως attribute.
Για τα tags foo
και bar
, το Latte αναγνωρίζει αυτόματα αν είναι
ζευγαρωτά tags, και αν ναι, μπορούν να γραφτούν αυτόματα χρησιμοποιώντας
n:attributes, συμπεριλαμβανομένων των παραλλαγών με προθέματα n:inner-foo
και n:tag-foo
.
Η σειρά εκτέλεσης τέτοιων n:attributes καθορίζεται από τη σειρά τους στον
πίνακα που επιστρέφεται από τη μέθοδο getTags()
. Έτσι, το n:foo
εκτελείται πάντα πριν από το n:bar
, ακόμα κι αν τα attributes στο HTML tag
αναφέρονται με την αντίστροφη σειρά, όπως <div n:bar="..." n:foo="...">
.
Εάν πρέπει να καθορίσετε τη σειρά των n:attributes σε πολλαπλές επεκτάσεις,
χρησιμοποιήστε τη βοηθητική μέθοδο order()
, όπου η παράμετρος
before
xor after
καθορίζει ποια tags ταξινομούνται πριν ή μετά
το tag.
public function getTags(): array
{
return [
'foo' => self::order(FooNode::create(...), before: 'bar'),
'bar' => self::order(BarNode::create(...), after: ['block', 'snippet']),
];
}
getPasses(): array
Καλείται κατά τη μεταγλώττιση του προτύπου. Επιστρέφει έναν συσχετιστικό πίνακα όνομα περάσματος ⇒ callable, που είναι συναρτήσεις που αντιπροσωπεύουν τα λεγόμενα compiler passes, τα οποία διασχίζουν και τροποποιούν το AST.
Και εδώ μπορεί να χρησιμοποιηθεί η βοηθητική μέθοδος order()
. Η
τιμή των παραμέτρων before
ή after
μπορεί να είναι *
με
την έννοια πριν/μετά από όλα.
public function getPasses(): array
{
return [
'optimize' => Passes::optimizePass(...),
'sandbox' => self::order($this->sandboxPass(...), before: '*'),
// ...
];
}
beforeRender (Latte\Engine $engine): void
Καλείται πριν από κάθε απόδοση του προτύπου. Η μέθοδος μπορεί να χρησιμοποιηθεί, για παράδειγμα, για την αρχικοποίηση μεταβλητών που χρησιμοποιούνται κατά την απόδοση.
getFilters(): array
Καλείται πριν από την απόδοση του προτύπου. Επιστρέφει φίλτρα ως συσχετιστικό πίνακα όνομα φίλτρου ⇒ callable. Περισσότερες πληροφορίες.
public function getFilters(): array
{
return [
'batch' => $this->batchFilter(...),
'trim' => $this->trimFilter(...),
// ...
];
}
getFunctions(): array
Καλείται πριν από την απόδοση του προτύπου. Επιστρέφει συναρτήσεις ως συσχετιστικό πίνακα όνομα συνάρτησης ⇒ callable. Περισσότερες πληροφορίες.
public function getFunctions(): array
{
return [
'clamp' => $this->clampFunction(...),
'divisibleBy' => $this->divisibleByFunction(...),
// ...
];
}
getProviders(): array
Καλείται πριν από την απόδοση του προτύπου. Επιστρέφει έναν πίνακα
παρόχων, οι οποίοι είναι συνήθως αντικείμενα που χρησιμοποιούνται από
τα tags κατά το χρόνο εκτέλεσης. Η πρόσβαση σε αυτά γίνεται μέσω του
$this->global->...
. Περισσότερες πληροφορίες.
public function getProviders(): array
{
return [
'myFoo' => $this->foo,
'myBar' => $this->bar,
// ...
];
}
getCacheKey (Latte\Engine $engine): mixed
Καλείται πριν από την απόδοση του προτύπου. Η τιμή επιστροφής γίνεται μέρος του κλειδιού, το hash του οποίου περιέχεται στο όνομα αρχείου του μεταγλωττισμένου προτύπου. Έτσι, για διαφορετικές τιμές επιστροφής, το Latte θα δημιουργήσει διαφορετικά αρχεία cache.