Praktyki dla programistów
Instalacja
Najlepszym sposobem na zainstalowanie Latte jest użycie Composera:
composer require latte/latte
Obsługiwane wersje PHP (dotyczy najnowszych wersji Latte z łatką):
wersja | kompatybilna z PHP |
---|---|
Latte 3.0 | PHP 8.0 – 8.2 |
Jak renderować szablon
Jak wyrenderować szablon? Wystarczy użyć tego prostego kodu:
$latte = new Latte\Engine;
// katalog podręczny
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* zmienne szablonu */ ];
// lub $params = new TemplateParameters(/* ... */);
// renderuj do wyjścia
$latte->render('template.latte', $params);
// lub renderuj do zmiennej
$output = $latte->renderToString('template.latte', $params);
Parametry mogą być tablicą lub jeszcze lepiej obiektem, który zapewnia sprawdzanie typu i podpowiadanie w edytorze.
Możesz również znaleźć przykłady użycia w repozytorium przykładów Latte.
Wydajność i buforowanie
Szablony Latte są niezwykle szybkie, ponieważ Latte kompiluje je bezpośrednio do kodu PHP i buforuje na dysku. Dzięki temu nie mają one żadnych dodatkowych kosztów ogólnych w porównaniu z szablonami napisanymi w czystym PHP.
Pamięć podręczna jest automatycznie regenerowana przy każdej zmianie pliku źródłowego. Możesz więc wygodnie edytować swoje szablony Latte podczas tworzenia i widzieć zmiany natychmiast w przeglądarce. Możesz wyłączyć tę funkcję w środowisku produkcyjnym i zaoszczędzić trochę wydajności:
$latte->setAutoRefresh(false);
Po wdrożeniu na serwerze produkcyjnym początkowe generowanie pamięci podręcznej, zwłaszcza w przypadku większych aplikacji, może, co zrozumiałe, zająć trochę czasu. Latte posiada wbudowane zabezpieczenie przed cache stampede. Jest to sytuacja, w której serwer otrzymuje dużą liczbę współbieżnych żądań, a ponieważ cache Latte jeszcze nie istnieje, wszystkie generowałyby go w tym samym czasie. Co powoduje kolce CPU. Latte jest inteligentny, a gdy istnieje wiele współbieżnych żądań, tylko pierwszy wątek generuje pamięć podręczną, pozostałe czekają, a następnie używają go.
Parametry jako klasa
Lepszym rozwiązaniem niż przekazywanie zmiennych do szablonu jako tablic jest stworzenie klasy. Otrzymujesz notację bezpieczną dla typu, ładną sugestię w IDE i sposób na rejestrację filtrów i funkcji.
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,
));
Wyłączenie automatycznej ucieczki zmiennych
Jeśli zmienna zawiera łańcuch HTML, możesz ją oznaczyć tak, aby Latte nie wykonywała automatycznego (a więc
podwójnego) escape'u. Pozwala to uniknąć konieczności określania |noescape
w szablonie.
Najprostszym sposobem jest zawinięcie łańcucha w obiekt Latte\Runtime\Html
:
$params = [
'articleBody' => new Latte\Runtime\Html($article->htmlBody),
];
Latte nie ucieka również wszystkim obiektom, które implementują interfejs Latte\HtmlStringable
. Możesz więc
stworzyć własną klasę, której metoda __toString()
będzie zwracała kod HTML, który nie będzie automatycznie
escape'owany:
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'),
];
Metoda __toString
musi zwracać poprawny HTML i zapewniać uciekanie parametrów, w przeciwnym
razie może wystąpić luka XSS!
Jak rozszerzyć Latte o filtry, tagi, itp.
Jak dodać niestandardowy filtr, funkcję, tag itp. do Latte? Jest to temat rozdziału Extending Latte. Jeśli chcesz ponownie użyć swoich dostosowań w różnych projektach lub podzielić się nimi z innymi, powinieneś utworzyć rozszerzenie.
Dowolny kod w szablonie {php ...}
Wewnątrz tagu {do}
może zawierać tylko wyrażenia PHP,
więc nie możesz wstawiać takich konstrukcji jak if ... else
czy wyrażenia zakończone średnikiem.
Można jednak zarejestrować rozszerzenie RawPhpExtension
, które dodaje znacznik {php ...}
. Można
go użyć do wstawienia dowolnego kodu PHP. Nie podlega on żadnym zasadom trybu piaskownicy, więc odpowiedzialność za jego
użycie ponosi autor szablonu.
$latte->addExtension(new Latte\Essential\RawPhpExtension);
Sprawdzanie wygenerowanego kodu
Latte kompiluje szablony do kodu PHP. Oczywiście zapewnia, że wygenerowany kod jest poprawny składniowo. Jednak w przypadku korzystania z rozszerzeń innych firm lub RawPhpExtension, Latte nie może zagwarantować poprawności wygenerowanego pliku. Ponadto w PHP można napisać kod, który jest poprawny składniowo, ale jest zabroniony (na przykład przypisanie wartości do zmiennej $this) i powoduje błąd kompilacji PHP. Jeśli napiszesz taką operację w szablonie, zostanie ona również uwzględniona w wygenerowanym kodzie PHP. Ponieważ w PHP istnieje ponad dwieście różnych niedozwolonych operacji, Latte nie ma na celu ich wykrywania. Samo PHP oznaczy je podczas renderowania, co zwykle nie stanowi problemu.
Istnieją jednak sytuacje, w których chcesz wiedzieć podczas kompilacji szablonu, że nie zawiera on błędów kompilacji PHP. Zwłaszcza, gdy szablony mogą być edytowane przez użytkowników lub korzystasz z Sandbox. W takim przypadku należy sprawdzić szablony podczas kompilacji. Możesz aktywować tę funkcjonalność za pomocą metody Engine::enablePhpLint(). Ponieważ musi ona wywołać plik binarny PHP w celu sprawdzenia, należy przekazać jego ścieżkę jako parametr:
$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
try {
$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
// wyłapuje błędy Latte, a także błąd kompilacji w PHP
echo 'Error: ' . $e->getMessage();
}
Lokalizacja
Latte pozwala ustawić ustawienia regionalne, które wpływają na formatowanie liczb, dat i sortowanie. Jest on ustawiany
przy użyciu metody setLocale()
. Identyfikator ustawień regionalnych jest zgodny ze standardem znaczników
językowych IETF, który wykorzystuje rozszerzenie PHP intl
. Składa się z kodu języka i ewentualnie kodu kraju,
na przykład en_US
dla języka angielskiego w Stanach Zjednoczonych, de_DE
dla języka niemieckiego w
Niemczech itp.
$latte = new Latte\Engine;
$latte->setLocale('cs');
Ustawienie locale wpływa na filtry localDate, sort, number i bytes.
Wymaga rozszerzenia PHP intl
. Ustawienie w Latte nie wpływa na globalne ustawienie locale
w PHP.
Tryb ścisły
W trybie ścisłego parsowania Latte sprawdza, czy nie brakuje zamykających znaczników HTML, a także wyłącza użycie
zmiennej $this
. Aby go włączyć:
$latte = new Latte\Engine;
$latte->setStrictParsing();
Aby wygenerować szablony z nagłówkiem declare(strict_types=1)
, wykonaj następujące czynności:
$latte = new Latte\Engine;
$latte->setStrictTypes();
Tłumaczenie w szablonach
Użyj rozszerzenia TranslatorExtension
, aby dodać tagi do swojego szablonu {_...}
, {translate}
i filtr translate
. Służy do tłumaczenia wartości lub części
szablonu na inne języki. Jako parametr określ metodę (callable PHP) wykonującą tłumaczenie:
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// utworzyć $translated z $original zgodnie z $this->lang
return $translated;
}
}
$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...), // [$translator, 'translate'] w PHP 8.0
);
$latte->addExtension($extension);
Tłumacz jest wywoływany w trybie runtime, gdy szablon jest renderowany. Jednak Latte może tłumaczyć wszystkie statyczne teksty podczas kompilacji szablonu. To oszczędza wydajność, ponieważ każdy ciąg jest tłumaczony tylko raz, a wynikowe tłumaczenie jest zapisywane do skompilowanego pliku. Tworzy to wiele skompilowanych wersji szablonu w katalogu cache, po jednej dla każdego języka. Aby to zrobić, musisz tylko określić język jako drugi parametr:
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
Przez tekst statyczny rozumiemy na przykład {_'hello'}
lub {translate}hello{/translate}
. Tekst
niestatyczny, taki jak {_$foo}
, będzie nadal tłumaczony w trybie runtime.
Szablon może również przekazać dodatkowe parametry do tłumacza poprzez {_$original, foo: bar}
lub
{translate foo: bar}
, które otrzymuje jako tablicę $params
:
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
Debugowanie i Tracy
Latte stara się, aby Twój rozwój był jak najbardziej przyjemny. Istnieją trzy znaczniki bezpośrednio do celów
debugowania {dump}
, {debugbreak}
a {trace}
.
Największą wygodę uzyskasz, jeśli jeszcze zainstalujesz świetny debugger Tracy i aktywujesz dodatek Latte:
// umożliwia Tracy
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// aktywuje rozszerzenie Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
Teraz zobaczysz wszystkie błędy na wyraźnym czerwonym ekranie, w tym błędy w szablonach z podświetleniem wierszy i kolumn (wideo). Jednocześnie w prawym dolnym rogu Tracy Bar pojawia się zakładka Latte, na której wyraźnie widać wszystkie wyrenderowane szablony i ich relacje (w tym możliwość kliknięcia w szablon lub skompilowany kod), a także zmienne:
Ponieważ Latte kompiluje szablony do czytelnego kodu PHP, możesz wygodnie przejść przez nie w swoim IDE.
Linter: Sprawdzanie poprawności składni szablonu
Narzędzie Linter pomoże Ci przejść przez wszystkie szablony i sprawdzić błędy składni. Jest ono uruchamiane z konsoli:
vendor/bin/latte-lint <path>
Użyj parametru --strict
, aby aktywować tryb ścisły.
Jeśli używasz niestandardowych znaczników, utwórz również swój niestandardowy Linter, np.
custom-latte-lint
:
#!/usr/bin/env php
<?php
// wprowadź rzeczywistą ścieżkę do pliku autoload.php
require __DIR__ . '/vendor/autoload.php';
$path = $argv[1] ?? '.';
$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// dodaj tutaj swoje indywidualne rozszerzenia
$latte->addExtension(/* ... */);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);
Alternatywnie, można przekazać własny obiekt Latte\Engine
do aplikacji Linter:
$latte = new Latte\Engine;
// tutaj konfigurujemy obiekt $latte
$linter = new Latte\Tools\Linter(engine: $latte);
Ładowanie szablonów z łańcucha
Potrzebujesz załadować szablony z ciągów znaków zamiast z plików, być może w celach testowych? StringLoader pomoże Ci w tym:
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file', $params);
Exception Handler
Możesz zdefiniować swój własny handler dla oczekiwanych wyjątków. Wyjątki zgłaszane wewnątrz {try}
i w piaskownicy są do niego przekazywane.
$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
$logger->log($e);
};
$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);
Automatyczne wyszukiwanie układu
Używając znacznika {layout}
szablon określa swój
szablon nadrzędny. Możliwe jest również automatyczne wyszukiwanie układu, co ułatwi pisanie szablonów, ponieważ nie będą
one musiały zawierać znacznika {layout}
.
Osiąga się to w następujący sposób:
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// zwraca ścieżkę do nadrzędnego pliku szablonu
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
Jeśli szablon nie powinien mieć układu, wskaże to za pomocą znacznika {layout none}
.