Πρακτικές για προγραμματιστές

Εγκατάσταση

Ο καλύτερος τρόπος εγκατάστασης του Latte είναι η χρήση ενός Composer:

composer require latte/latte

Latte: Υποστηριζόμενες εκδόσεις PHP (ισχύει για τις πιο πρόσφατες εκδόσεις της Latte):

έκδοση συμβατή με PHP
Latte 3.0 PHP 8.0 – 8.2

Πώς να αποδώσετε ένα πρότυπο

Πώς να αποδώσετε ένα πρότυπο; Χρησιμοποιήστε αυτόν τον απλό κώδικα:

$latte = new Latte\Engine;
// κατάλογος cache
$latte->setTempDirectory('/path/to/tempdir');

$params = [ /* template variables */ ];
// ή $params = new TemplateParameters(/* ... */),

// απόδοση στην έξοδο
$latte->render('template.latte', $params);
// ή απόδοση σε μεταβλητή
$output = $latte->renderToString('template.latte', $params);

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

Μπορείτε επίσης να βρείτε παραδείγματα χρήσης στο αποθετήριο Latte examples.

Απόδοση και προσωρινή αποθήκευση

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

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

$latte->setAutoRefresh(false);

Όταν αναπτύσσεται σε έναν διακομιστή παραγωγής, η αρχική δημιουργία προσωρινής μνήμης, ειδικά για μεγαλύτερες εφαρμογές, μπορεί δικαιολογημένα να πάρει αρκετό χρόνο. Το Latte διαθέτει ενσωματωμένη πρόληψη κατά του cache stampede. Πρόκειται για μια κατάσταση όπου ο διακομιστής λαμβάνει μεγάλο αριθμό ταυτόχρονων αιτήσεων και επειδή η κρυφή μνήμη cache του Latte δεν υπάρχει ακόμα, θα την δημιουργούσαν όλες ταυτόχρονα. Το οποίο αυξάνει την CPU. Το Latte είναι έξυπνο, και όταν υπάρχουν πολλαπλές ταυτόχρονες αιτήσεις, μόνο το πρώτο νήμα δημιουργεί την κρυφή μνήμη, τα υπόλοιπα περιμένουν και στη συνέχεια τη χρησιμοποιούν.

Παράμετροι ως κλάση

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

class MailTemplateParameters
{
	public function __construct(
		public string $lang,
		public Address $address,
		public string $subject,
		public array $items,
		public ?float $price = null,
	) {}
}

$latte->render('mail.latte', new MailTemplateParameters(
	lang: $this->lang,
	subject: $title,
	price: $this->getPrice(),
	items: [],
	address: $userAddress,
));

Απενεργοποίηση του Auto-Escaping της μεταβλητής

Εάν η μεταβλητή περιέχει μια συμβολοσειρά HTML, μπορείτε να τη σημειώσετε έτσι ώστε το Latte να μην την αποφεύγει αυτόματα (και επομένως διπλά). Με αυτόν τον τρόπο αποφεύγεται η ανάγκη προσδιορισμού του |noescape στο πρότυπο.

Ο ευκολότερος τρόπος είναι να τυλίξετε το αλφαριθμητικό σε ένα αντικείμενο Latte\Runtime\Html:

$params = [
	'articleBody' => new Latte\Runtime\Html($article->htmlBody),
];

Latte δεν αποφεύγει επίσης όλα τα αντικείμενα που υλοποιούν τη διεπαφή Latte\HtmlStringable. Έτσι, μπορείτε να δημιουργήσετε τη δική σας κλάση της οποίας η μέθοδος __toString() θα επιστρέφει κώδικα HTML που δεν θα αποφεύγεται αυτόματα:

class Emphasis extends Latte\HtmlStringable
{
	public function __construct(
		private string $str,
	) {
	}

	public function __toString(): string
	{
		return '<em>' . htmlspecialchars($this->str) . '</em>';
	}
}

$params = [
	'foo' => new Emphasis('hello'),
];

Η μέθοδος __toString πρέπει να επιστρέφει σωστή HTML και να παρέχει escaping παραμέτρων, διαφορετικά μπορεί να προκύψει ευπάθεια XSS!

Πώς να επεκτείνετε το Latte με φίλτρα, ετικέτες κ.λπ.

Πώς να προσθέσετε ένα προσαρμοσμένο φίλτρο, μια λειτουργία, μια ετικέτα κ.λπ. στο Latte; Μάθετε στο κεφάλαιο επέκταση της Latte. Αν θέλετε να επαναχρησιμοποιήσετε τις αλλαγές σας σε διαφορετικά έργα ή αν θέλετε να τις μοιραστείτε με άλλους, τότε θα πρέπει να δημιουργήσετε μια επέκταση.

Οποιοσδήποτε κώδικας στο πρότυπο {php ...}

Μόνο εκφράσεις PHP μπορούν να γραφτούν μέσα στο {do} tag, οπότε δεν μπορείτε, για παράδειγμα, να εισάγετε δομές όπως if ... else ή δηλώσεις με τελεία και παύλα.

Ωστόσο, μπορείτε να καταχωρίσετε την επέκταση RawPhpExtension, η οποία προσθέτει την ετικέτα {php ...}. Μπορείτε να το χρησιμοποιήσετε για να εισαγάγετε οποιοδήποτε κώδικα PHP. Δεν υπόκειται σε κανέναν κανόνα λειτουργίας sandbox, οπότε η χρήση της είναι ευθύνη του συγγραφέα του προτύπου.

$latte->addExtension(new Latte\Essential\RawPhpExtension);

Έλεγχος παραγόμενου κώδικα

Το Latte μετατρέπει τα πρότυπα σε κώδικα PHP. Φυσικά, διασφαλίζει ότι ο παραγόμενος κώδικας είναι συντακτικά έγκυρος. Ωστόσο, όταν χρησιμοποιούνται επεκτάσεις τρίτων ή το RawPhpExtension, η Latte δεν μπορεί να εγγυηθεί την ορθότητα του παραγόμενου αρχείου. Επίσης, στην PHP, μπορείτε να γράψετε κώδικα που είναι συντακτικά σωστός, αλλά είναι απαγορευμένος (για παράδειγμα, εκχώρηση τιμής στη μεταβλητή $this) και προκαλεί ένα PHP Compile Error. Αν γράψετε μια τέτοια λειτουργία σε ένα πρότυπο, θα συμπεριληφθεί και στον παραγόμενο κώδικα PHP. Δεδομένου ότι υπάρχουν πάνω από διακόσιες διαφορετικές απαγορευμένες λειτουργίες στην PHP, το Latte δεν στοχεύει στον εντοπισμό τους. Η ίδια η PHP θα τις επισημάνει κατά την απόδοση, κάτι που συνήθως δεν αποτελεί πρόβλημα.

Ωστόσο, υπάρχουν περιπτώσεις όπου θέλετε να γνωρίζετε κατά τη διάρκεια της σύνταξης του προτύπου ότι δεν περιέχει σφάλματα σύνταξης PHP. Ειδικά όταν τα πρότυπα μπορούν να επεξεργαστούν από χρήστες ή όταν χρησιμοποιείτε Sandbox. Σε μια τέτοια περίπτωση, να ελέγχετε τα πρότυπα κατά τη διάρκεια της μεταγλώττισης. Μπορείτε να ενεργοποιήσετε αυτή τη λειτουργικότητα χρησιμοποιώντας τη μέθοδο Engine::enablePhpLint(). Δεδομένου ότι χρειάζεται να καλέσει το δυαδικό αρχείο PHP για τον έλεγχο, περάστε τη διαδρομή του ως παράμετρο:

$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');

try {
	$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
	// πιάνει λάθη Latte και επίσης Compile Error σε PHP
	echo 'Error: ' . $e->getMessage();
}

Αυστηρή λειτουργία

Στην αυστηρή λειτουργία ανάλυσης, η Latte ελέγχει για ελλείψεις κλεισίματος ετικετών HTML και επίσης απενεργοποιεί τη χρήση της μεταβλητής $this. Για να την ενεργοποιήσετε:

$latte = new Latte\Engine;
$latte->setStrictParsing();

Για να δημιουργήσετε πρότυπα με την επικεφαλίδα declare(strict_types=1), κάντε τα εξής:

$latte = new Latte\Engine;
$latte->setStrictTypes();

Μετάφραση σε πρότυπα

Χρησιμοποιήστε την επέκταση TranslatorExtension για να προσθέσετε {_...}, {translate} και φιλτράρετε translate στο πρότυπο. Χρησιμοποιούνται για τη μετάφραση τιμών ή τμημάτων του προτύπου σε άλλες γλώσσες. Η παράμετρος είναι η μέθοδος (PHP callable) που εκτελεί τη μετάφραση:

class MyTranslator
{
	public function __construct(private string $lang)
	{}

	public function translate(string $original): string
	{
		// δημιουργία $translated από $original σύμφωνα με $this->lang
		return $translated;
	}
}

$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
	$translator->translate(...), // [$translator, 'translate'] σε PHP 8.0
);
$latte->addExtension($extension);

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

$extension = new Latte\Essential\TranslatorExtension(
	$translator->translate(...),
	$lang,
);

Με τον όρο στατικό κείμενο εννοούμε, για παράδειγμα, το {_'hello'} ή το {translate}hello{/translate}. Μη στατικό κείμενο, όπως το {_$foo}, θα συνεχίσει να μεταφράζεται κατά την εκτέλεση.

Το πρότυπο μπορεί επίσης να περάσει πρόσθετες παραμέτρους στον μεταφραστή μέσω των {_$original, foo: bar} ή {translate foo: bar}, τις οποίες λαμβάνει ως πίνακα $params:

public function translate(string $original, ...$params): string
{
	// $params['foo'] === 'bar'
}

Αποσφαλμάτωση και Tracy

Η Latte προσπαθεί να κάνει την ανάπτυξη όσο το δυνατόν πιο ευχάριστη. Για σκοπούς αποσφαλμάτωσης, υπάρχουν τρεις ετικέτες {dump}, {debugbreak} και {trace}.

Θα έχετε τη μεγαλύτερη άνεση αν εγκαταστήσετε το εξαιρετικό εργαλείο εντοπισμού σφαλμάτων Tracy και ενεργοποιήσετε το πρόσθετο Latte:

// επιτρέπει Tracy
Tracy\Debugger::enable();

$latte = new Latte\Engine;
// ενεργοποιεί την επέκταση της Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);

Τώρα θα βλέπετε όλα τα σφάλματα σε μια καθαρή κόκκινη οθόνη, συμπεριλαμβανομένων των σφαλμάτων σε πρότυπα με επισήμανση γραμμών και στηλών (βίντεο). Ταυτόχρονα, στην κάτω δεξιά γωνία στη λεγόμενη Tracy Bar, εμφανίζεται μια καρτέλα για το Latte, όπου μπορείτε να δείτε ξεκάθαρα όλα τα αποδιδόμενα πρότυπα και τις σχέσεις τους (συμπεριλαμβανομένης της δυνατότητας να κάνετε κλικ στο πρότυπο ή στον μεταγλωττισμένο κώδικα), καθώς και τις μεταβλητές:

Δεδομένου ότι το Latte μεταγλωττίζει τα πρότυπα σε αναγνώσιμο κώδικα PHP, μπορείτε εύκολα να τα διαβάσετε στο IDE σας.

Linter: Επικύρωση του συντακτικού του προτύπου

Το εργαλείο Linter θα σας βοηθήσει να περάσετε από όλα τα πρότυπα και να ελέγξετε για συντακτικά λάθη. Εκκινείται από την κονσόλα:

vendor/bin/latte-lint <path>

Χρησιμοποιήστε την παράμετρο --strict για να ενεργοποιήσετε την αυστηρή λειτουργία.

Εάν χρησιμοποιείτε προσαρμοσμένες ετικέτες, δημιουργήστε επίσης τον προσαρμοσμένο σας Linter, π.χ. custom-latte-lint:

#!/usr/bin/env php
<?php

// εισάγετε την πραγματική διαδρομή προς το αρχείο autoload.php
require __DIR__ . '/vendor/autoload.php';

$path = $argv[1] ?? '.';

$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// προσθέστε τις μεμονωμένες επεκτάσεις σας εδώ
$latte->addExtension(/* ... */);

$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);

Εναλλακτικά, μπορείτε να περάσετε το δικό σας αντικείμενο Latte\Engine στον Linter:

$latte = new Latte\Engine;
// εδώ ρυθμίζουμε το αντικείμενο $latte
$linter = new Latte\Tools\Linter(engine: $latte);

Φόρτωση προτύπων από μια συμβολοσειρά

Χρειάζεται να φορτώσετε πρότυπα από συμβολοσειρές αντί για αρχεία, ίσως για σκοπούς δοκιμών; Το StringLoader θα σας βοηθήσει:

$latte->setLoader(new Latte\Loaders\StringLoader([
	'main.file' => '{include other.file}',
	'other.file' => '{if true} {$var} {/if}',
]));

$latte->render('main.file', $params);

Χειριστής εξαιρέσεων

Μπορείτε να ορίσετε το δικό σας χειριστή για τις αναμενόμενες εξαιρέσεις. Εξαιρέσεις που εγείρονται μέσα σε {try} και στο sandbox, μεταβιβάζονται σε αυτόν.

$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
	$logger->log($e);
};

$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);

Αυτόματη αναζήτηση διάταξης

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

Αυτό επιτυγχάνεται ως εξής:

$finder = function (Latte\Runtime\Template $template) {
	if (!$template->getReferenceType()) {
		// επιστρέφει τη διαδρομή προς το γονικό αρχείο προτύπου
		return 'automatic.layout.latte';
	}
};

$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);

Εάν το πρότυπο δεν πρέπει να έχει διάταξη, θα το υποδείξει με την ετικέτα {layout none}.

έκδοση: 3.0