Nette Documentation Preview

syntax
Procedury deweloperskie
***********************


Instalacja
==========

Najlepszym sposobem na zainstalowanie Latte jest użycie Composera:

```shell
composer require latte/latte
```

Obsługiwane wersje PHP (dotyczy najnowszych wersji Latte):

| wersja          | kompatybilny z PHP
|-----------------|-------------------
| Latte 3.0       | PHP 8.0 – 8.2


Jak renderować szablon
======================

Jak wyrenderować szablon? Wystarczy ten prosty kod:

```php
$latte = new Latte\Engine;
// katalog dla cache
$latte->setTempDirectory('/path/to/tempdir');

$params = [ /* zmienne szablonu */ ];
// lub $params = new TemplateParameters(/* ... */);

// renderuj na wyjście
$latte->render('template.latte', $params);
// renderuj do zmiennej
$output = $latte->renderToString('template.latte', $params);
```

Parametry mogą być tablicą lub, jeszcze lepiej, [obiektem |#Parametry jako klasa], który zapewni kontrolę typów i podpowiadanie w edytorach.

.[note]
Przykłady użycia można znaleźć również w repozytorium [Przykłady Latte |https://github.com/nette-examples/latte].


Wydajność i cache
=================

Szablony w Latte są niezwykle szybkie, ponieważ Latte kompiluje je bezpośrednio do kodu PHP i zapisuje w pamięci podręcznej na dysku. Dzięki temu nie mają żadnego dodatkowego narzutu w porównaniu do szablonów napisanych w czystym PHP.

Cache jest automatycznie regenerowany za każdym razem, gdy zmienisz plik źródłowy. Podczas rozwoju możesz więc wygodnie edytować szablony w Latte, a zmiany natychmiast widzieć w przeglądarce. Możesz wyłączyć tę funkcję w środowisku produkcyjnym, aby zaoszczędzić trochę wydajności:

```php
$latte->setAutoRefresh(false);
```

Podczas wdrażania na serwerze produkcyjnym, początkowe wygenerowanie cache, zwłaszcza w przypadku większych aplikacji, może oczywiście chwilę potrwać. Latte ma wbudowaną prewencję przed "cache stampede":https://en.wikipedia.org/wiki/Cache_stampede. Jest to sytuacja, w której pojawia się większa liczba jednoczesnych żądań uruchamiających Latte, a ponieważ cache jeszcze nie istnieje, wszystkie zaczęłyby go generować jednocześnie. Co nieproporcjonalnie obciążyłoby serwer. Latte jest sprytne i przy wielu jednoczesnych żądaniach cache generuje tylko pierwszy wątek, pozostałe czekają, a następnie go wykorzystują.


Parametry jako klasa
====================

Lepiej niż przekazywać zmienne do szablonu jako tablicę jest utworzyć klasę. Zyskasz w ten sposób [zapis bezpieczny typowo |type-system], [przyjemne podpowiadanie w IDE |recipes#Edytory i IDE] oraz drogę do [rejestracji filtrów |custom-filters#Filtry używające klasy z atrybutami] i [funkcji |custom-functions#Funkcje używające klasy z atrybutami].

```php
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łączanie automatycznego escapowania zmiennej
==============================================

Jeśli zmienna zawiera ciąg znaków w HTML, możesz ją oznaczyć tak, aby Latte automatycznie (a więc podwójnie) jej nie escapowało. Unikniesz w ten sposób konieczności używania w szablonie `|noescape`.

Najprostszym sposobem jest opakowanie ciągu znaków w obiekt `Latte\Runtime\Html`:

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

Latte ponadto nie escapuje wszystkich obiektów, które implementują interfejs `Latte\HtmlStringable`. Możesz więc stworzyć własną klasę, której metoda `__toString()` będzie zwracać kod HTML, który nie będzie automatycznie escapowany:

```php
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'),
];
```

.[warning]
Metoda `__toString` musi zwracać poprawny HTML i zapewniać escapowanie parametrów, w przeciwnym razie może dojść do podatności XSS!


Jak rozszerzyć Latte o filtry, znaczniki itp.
=============================================

Jak dodać do Latte własny filtr, funkcję, znacznik itp.? O tym traktuje rozdział [rozszerzanie Latte |extending-latte]. Jeśli chcesz ponownie wykorzystać swoje modyfikacje w różnych projektach lub podzielić się nimi z innymi, powinieneś [utworzyć rozszerzenie |extending-latte#Latte Extension].


Dowolny kod w szablonie `{php ...}` .{toc: RawPhpExtension}
===========================================================

Wewnątrz znacznika [`{do}` |tags#do] można zapisywać tylko wyrażenia PHP, nie można więc na przykład wstawiać konstrukcji takich jak `if ... else` ani instrukcji zakończonych średnikiem.

Można jednak zarejestrować rozszerzenie `RawPhpExtension`, które dodaje znacznik `{php ...}`. Za jego pomocą można wstawiać dowolny kod PHP. Nie obowiązują go żadne zasady trybu sandbox, użycie jest więc na odpowiedzialność autora szablonu.

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


Kontrola wygenerowanego kodu .{data-version:3.0.7}
==================================================

Latte kompiluje szablony do kodu PHP. Oczywiście dba o to, aby wygenerowany kod był składniowo poprawny. Jednak przy użyciu rozszerzeń stron trzecich lub `RawPhpExtension` Latte nie może zagwarantować poprawności wygenerowanego pliku. Można również napisać w PHP kod, który jest wprawdzie składniowo poprawny, ale jest zabroniony (na przykład przypisanie wartości do zmiennej `$this`) i spowoduje PHP Compile Error. Jeśli taką operację zapiszesz w szablonie, trafi ona również do wygenerowanego kodu PHP. Ponieważ w PHP istnieje ponad dwieście różnych zabronionych operacji, Latte nie ma ambicji ich wykrywać. Zwróci na nie uwagę dopiero samo PHP podczas renderowania, co zazwyczaj niczemu nie szkodzi.

Są jednak sytuacje, w których chcesz wiedzieć już w momencie kompilacji szablonu, że nie zawiera on żadnego PHP Compile Error. Zwłaszcza wtedy, gdy szablony mogą edytować użytkownicy lub używasz [Sandbox |sandbox]. W takim przypadku zlecaj kontrolę szablonów już w czasie kompilacji. Tę funkcjonalność włączysz metodą `Engine::enablePhpLint()`. Ponieważ do kontroli potrzebuje wywołać binarkę PHP, przekaż do niej ścieżkę jako parametr:

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

try {
	$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
	// przechwytuje błędy w Latte, a także Compile Error w PHP
	echo 'Błąd: ' . $e->getMessage();
}
```


Ustawienia regionalne .{data-version:3.0.18}{toc: Locale}
=========================================================

Latte pozwala ustawić ustawienia regionalne (locale), które wpływają na formatowanie liczb, dat i sortowanie. Ustawia się je za pomocą metody `setLocale()`. Identyfikator ustawień regionalnych jest zgodny ze standardem IETF language tag, który używa rozszerzenie PHP `intl`. Składa się z kodu języka i opcjonalnie kodu kraju, np. `en_US` dla angielskiego w Stanach Zjednoczonych, `de_DE` dla niemieckiego w Niemczech, `pl_PL` dla polskiego w Polsce itp.

```php
$latte = new Latte\Engine;
$latte->setLocale('pl_PL');
```

Ustawienie locale wpływa na filtry [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] oraz [bytes |filters#bytes].

.[note]
Wymaga rozszerzenia PHP `intl`. Ustawienie w Latte nie wpływa na globalne ustawienia locale w PHP.


Tryb ścisły .{data-version:3.0.8}
=================================

W trybie ścisłego parsowania Latte kontroluje, czy nie brakuje zamykających znaczników HTML, a także zabrania używania zmiennej `$this`. Włączysz go w ten sposób:

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

Generowanie szablonów z nagłówkiem `declare(strict_types=1)` włączysz w ten sposób:

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


Tłumaczenie w szablonach .{toc: TranslatorExtension}
====================================================

Za pomocą rozszerzenia `TranslatorExtension` dodasz do szablonu znaczniki [`{_...}` |tags#], [`{translate}` |tags#translate] oraz filtr [`translate` |filters#translate]. Służą one do tłumaczenia wartości lub części szablonu na inne języki. Jako parametr podajemy metodę (PHP callable) wykonującą tłumaczenie:

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

	public function translate(string $original): string
	{
		// z $original tworzymy $translated 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);
```

Translator jest wywoływany w czasie działania podczas renderowania szablonu. Latte potrafi jednak wszystkie statyczne teksty tłumaczyć już podczas kompilacji szablonu. Oszczędza to wydajność, ponieważ każdy ciąg znaków jest tłumaczony tylko raz, a wynikowe tłumaczenie jest zapisywane w skompilowanej postaci. W katalogu z cache powstaje więc więcej skompilowanych wersji szablonu, jedna dla każdego języka. W tym celu wystarczy podać język jako drugi parametr:

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

Tekstem statycznym jest na przykład `{_'hello'}` lub `{translate}hello{/translate}`. Teksty niestatyczne, jak na przykład `{_$foo}`, nadal będą tłumaczone w czasie działania.

Tłumaczowi można z szablonu przekazywać również dodatkowe parametry za pomocą `{_$original, foo: bar}` lub `{translate foo: bar}`, które otrzyma jako tablicę `$params`:

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


Debugowanie i Tracy
===================

Latte stara się jak najbardziej ułatwić Ci rozwój. Bezpośrednio do celów debugowania istnieje trójka znaczników [`{dump}` |tags#dump], [`{debugbreak}` |tags#debugbreak] oraz [`{trace}` |tags#trace].

Największy komfort uzyskasz, jeśli zainstalujesz jeszcze świetne [narzędzie do debugowania Tracy |tracy:] i aktywujesz dodatek dla Latte:

```php
// włącza Tracy
Tracy\Debugger::enable();

$latte = new Latte\Engine;
// aktywuje rozszerzenie dla Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
```

Teraz wszystkie błędy będą wyświetlane na przejrzystym czerwonym ekranie, w tym błędy w szablonach z podświetleniem wiersza i kolumny ([wideo |https://github.com/nette/tracy/releases/tag/v2.9.0]). Jednocześnie w prawym dolnym rogu, w tzw. Tracy Barze, pojawi się zakładka dla Latte, gdzie przejrzyście widać wszystkie renderowane szablony i ich wzajemne relacje (włącznie z możliwością przejścia do szablonu lub skompilowanego kodu) oraz zmienne:

[* latte-debugging.webp *]

Ponieważ Latte kompiluje szablony do przejrzystego kodu PHP, możesz je wygodnie krokować w swoim IDE.


Linter: walidacja składni szablonów .{toc: Linter}
==================================================

Przejrzeć wszystkie szablony i sprawdzić, czy nie zawierają błędów składniowych, pomoże Ci narzędzie Linter. Uruchamia się je z konsoli:

```shell
vendor/bin/latte-lint <ścieżka>
```

Parametrem `--strict` aktywujesz [#tryb ścisły].

Jeśli używasz własnych znaczników, utwórz również własną wersję Lintera, np. `custom-latte-lint`:

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

// podaj rzeczywistą ścieżkę do pliku autoload.php
require __DIR__ . '/vendor/autoload.php';

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

$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// tutaj dodaj swoje poszczególne rozszerzenia
$latte->addExtension(/* ... */);

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

Alternatywnie możesz przekazać własny obiekt `Latte\Engine` do Lintera:

```php
$latte = new Latte\Engine;
// tutaj konfigurujemy obiekt $latte
$linter = new Latte\Tools\Linter(engine: $latte);
```


Ładowanie szablonów z ciągu znaków
==================================

Potrzebujesz ładować szablony z ciągów znaków zamiast plików, na przykład do celów testowania? Pomoże Ci [StringLoader |loaders#StringLoader]:

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

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


Obsługa wyjątków
================

Możesz zdefiniować własny handler do obsługi oczekiwanych wyjątków. Przekazane zostaną mu wyjątki powstałe wewnątrz [`{try}` |tags#try] oraz w [sandboxie |sandbox].

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

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


Automatyczne wyszukiwanie layoutu
=================================

Za pomocą znacznika [`{layout}` |template-inheritance#Dziedziczenie layoutu] szablon określa swój szablon nadrzędny. Możliwe jest również automatyczne wyszukiwanie layoutu, co uprości pisanie szablonów, ponieważ nie będzie w nich konieczne używanie znacznika `{layout}`.

Osiąga się to w następujący sposób:

```php
$finder = function (Latte\Runtime\Template $template) {
	if (!$template->getReferenceType()) {
		// zwraca ścieżkę do pliku layoutu
		return 'automatic.layout.latte';
	}
};

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

Jeśli szablon nie ma mieć layoutu, informuje o tym znacznikiem `{layout none}`.

Procedury deweloperskie

Instalacja

Najlepszym sposobem na zainstalowanie Latte jest użycie Composera:

composer require latte/latte

Obsługiwane wersje PHP (dotyczy najnowszych wersji Latte):

wersja kompatybilny z PHP
Latte 3.0 PHP 8.0 – 8.2

Jak renderować szablon

Jak wyrenderować szablon? Wystarczy ten prosty kod:

$latte = new Latte\Engine;
// katalog dla cache
$latte->setTempDirectory('/path/to/tempdir');

$params = [ /* zmienne szablonu */ ];
// lub $params = new TemplateParameters(/* ... */);

// renderuj na wyjście
$latte->render('template.latte', $params);
// renderuj do zmiennej
$output = $latte->renderToString('template.latte', $params);

Parametry mogą być tablicą lub, jeszcze lepiej, obiektem, który zapewni kontrolę typów i podpowiadanie w edytorach.

Przykłady użycia można znaleźć również w repozytorium Przykłady Latte.

Wydajność i cache

Szablony w Latte są niezwykle szybkie, ponieważ Latte kompiluje je bezpośrednio do kodu PHP i zapisuje w pamięci podręcznej na dysku. Dzięki temu nie mają żadnego dodatkowego narzutu w porównaniu do szablonów napisanych w czystym PHP.

Cache jest automatycznie regenerowany za każdym razem, gdy zmienisz plik źródłowy. Podczas rozwoju możesz więc wygodnie edytować szablony w Latte, a zmiany natychmiast widzieć w przeglądarce. Możesz wyłączyć tę funkcję w środowisku produkcyjnym, aby zaoszczędzić trochę wydajności:

$latte->setAutoRefresh(false);

Podczas wdrażania na serwerze produkcyjnym, początkowe wygenerowanie cache, zwłaszcza w przypadku większych aplikacji, może oczywiście chwilę potrwać. Latte ma wbudowaną prewencję przed cache stampede. Jest to sytuacja, w której pojawia się większa liczba jednoczesnych żądań uruchamiających Latte, a ponieważ cache jeszcze nie istnieje, wszystkie zaczęłyby go generować jednocześnie. Co nieproporcjonalnie obciążyłoby serwer. Latte jest sprytne i przy wielu jednoczesnych żądaniach cache generuje tylko pierwszy wątek, pozostałe czekają, a następnie go wykorzystują.

Parametry jako klasa

Lepiej niż przekazywać zmienne do szablonu jako tablicę jest utworzyć klasę. Zyskasz w ten sposób zapis bezpieczny typowo, przyjemne podpowiadanie w IDE oraz drogę do rejestracji filtrówfunkcji.

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łączanie automatycznego escapowania zmiennej

Jeśli zmienna zawiera ciąg znaków w HTML, możesz ją oznaczyć tak, aby Latte automatycznie (a więc podwójnie) jej nie escapowało. Unikniesz w ten sposób konieczności używania w szablonie |noescape.

Najprostszym sposobem jest opakowanie ciągu znaków w obiekt Latte\Runtime\Html:

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

Latte ponadto nie escapuje wszystkich obiektów, które implementują interfejs Latte\HtmlStringable. Możesz więc stworzyć własną klasę, której metoda __toString() będzie zwracać kod HTML, który nie będzie automatycznie escapowany:

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ć escapowanie parametrów, w przeciwnym razie może dojść do podatności XSS!

Jak rozszerzyć Latte o filtry, znaczniki itp.

Jak dodać do Latte własny filtr, funkcję, znacznik itp.? O tym traktuje rozdział rozszerzanie Latte. Jeśli chcesz ponownie wykorzystać swoje modyfikacje w różnych projektach lub podzielić się nimi z innymi, powinieneś utworzyć rozszerzenie.

Dowolny kod w szablonie {php ...}

Wewnątrz znacznika {do} można zapisywać tylko wyrażenia PHP, nie można więc na przykład wstawiać konstrukcji takich jak if ... else ani instrukcji zakończonych średnikiem.

Można jednak zarejestrować rozszerzenie RawPhpExtension, które dodaje znacznik {php ...}. Za jego pomocą można wstawiać dowolny kod PHP. Nie obowiązują go żadne zasady trybu sandbox, użycie jest więc na odpowiedzialność autora szablonu.

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

Kontrola wygenerowanego kodu

Latte kompiluje szablony do kodu PHP. Oczywiście dba o to, aby wygenerowany kod był składniowo poprawny. Jednak przy użyciu rozszerzeń stron trzecich lub RawPhpExtension Latte nie może zagwarantować poprawności wygenerowanego pliku. Można również napisać w PHP kod, który jest wprawdzie składniowo poprawny, ale jest zabroniony (na przykład przypisanie wartości do zmiennej $this) i spowoduje PHP Compile Error. Jeśli taką operację zapiszesz w szablonie, trafi ona również do wygenerowanego kodu PHP. Ponieważ w PHP istnieje ponad dwieście różnych zabronionych operacji, Latte nie ma ambicji ich wykrywać. Zwróci na nie uwagę dopiero samo PHP podczas renderowania, co zazwyczaj niczemu nie szkodzi.

Są jednak sytuacje, w których chcesz wiedzieć już w momencie kompilacji szablonu, że nie zawiera on żadnego PHP Compile Error. Zwłaszcza wtedy, gdy szablony mogą edytować użytkownicy lub używasz Sandbox. W takim przypadku zlecaj kontrolę szablonów już w czasie kompilacji. Tę funkcjonalność włączysz metodą Engine::enablePhpLint(). Ponieważ do kontroli potrzebuje wywołać binarkę PHP, przekaż do niej ścieżkę jako parametr:

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

try {
	$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
	// przechwytuje błędy w Latte, a także Compile Error w PHP
	echo 'Błąd: ' . $e->getMessage();
}

Ustawienia regionalne

Latte pozwala ustawić ustawienia regionalne (locale), które wpływają na formatowanie liczb, dat i sortowanie. Ustawia się je za pomocą metody setLocale(). Identyfikator ustawień regionalnych jest zgodny ze standardem IETF language tag, który używa rozszerzenie PHP intl. Składa się z kodu języka i opcjonalnie kodu kraju, np. en_US dla angielskiego w Stanach Zjednoczonych, de_DE dla niemieckiego w Niemczech, pl_PL dla polskiego w Polsce itp.

$latte = new Latte\Engine;
$latte->setLocale('pl_PL');

Ustawienie locale wpływa na filtry localDate, sort, number oraz bytes.

Wymaga rozszerzenia PHP intl. Ustawienie w Latte nie wpływa na globalne ustawienia locale w PHP.

Tryb ścisły

W trybie ścisłego parsowania Latte kontroluje, czy nie brakuje zamykających znaczników HTML, a także zabrania używania zmiennej $this. Włączysz go w ten sposób:

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

Generowanie szablonów z nagłówkiem declare(strict_types=1) włączysz w ten sposób:

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

Tłumaczenie w szablonach

Za pomocą rozszerzenia TranslatorExtension dodasz do szablonu znaczniki {_...}, {translate} oraz filtr translate. Służą one do tłumaczenia wartości lub części szablonu na inne języki. Jako parametr podajemy metodę (PHP callable) wykonującą tłumaczenie:

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

	public function translate(string $original): string
	{
		// z $original tworzymy $translated 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);

Translator jest wywoływany w czasie działania podczas renderowania szablonu. Latte potrafi jednak wszystkie statyczne teksty tłumaczyć już podczas kompilacji szablonu. Oszczędza to wydajność, ponieważ każdy ciąg znaków jest tłumaczony tylko raz, a wynikowe tłumaczenie jest zapisywane w skompilowanej postaci. W katalogu z cache powstaje więc więcej skompilowanych wersji szablonu, jedna dla każdego języka. W tym celu wystarczy podać język jako drugi parametr:

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

Tekstem statycznym jest na przykład {_'hello'} lub {translate}hello{/translate}. Teksty niestatyczne, jak na przykład {_$foo}, nadal będą tłumaczone w czasie działania.

Tłumaczowi można z szablonu przekazywać również dodatkowe parametry za pomocą {_$original, foo: bar} lub {translate foo: bar}, które otrzyma jako tablicę $params:

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

Debugowanie i Tracy

Latte stara się jak najbardziej ułatwić Ci rozwój. Bezpośrednio do celów debugowania istnieje trójka znaczników {dump}, {debugbreak} oraz {trace}.

Największy komfort uzyskasz, jeśli zainstalujesz jeszcze świetne narzędzie do debugowania Tracy i aktywujesz dodatek dla Latte:

// włącza Tracy
Tracy\Debugger::enable();

$latte = new Latte\Engine;
// aktywuje rozszerzenie dla Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);

Teraz wszystkie błędy będą wyświetlane na przejrzystym czerwonym ekranie, w tym błędy w szablonach z podświetleniem wiersza i kolumny (wideo). Jednocześnie w prawym dolnym rogu, w tzw. Tracy Barze, pojawi się zakładka dla Latte, gdzie przejrzyście widać wszystkie renderowane szablony i ich wzajemne relacje (włącznie z możliwością przejścia do szablonu lub skompilowanego kodu) oraz zmienne:

Ponieważ Latte kompiluje szablony do przejrzystego kodu PHP, możesz je wygodnie krokować w swoim IDE.

Linter: walidacja składni szablonów

Przejrzeć wszystkie szablony i sprawdzić, czy nie zawierają błędów składniowych, pomoże Ci narzędzie Linter. Uruchamia się je z konsoli:

vendor/bin/latte-lint <ścieżka>

Parametrem --strict aktywujesz tryb ścisły.

Jeśli używasz własnych znaczników, utwórz również własną wersję Lintera, np. custom-latte-lint:

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

// podaj rzeczywistą ścieżkę do pliku autoload.php
require __DIR__ . '/vendor/autoload.php';

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

$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// tutaj dodaj swoje poszczególne rozszerzenia
$latte->addExtension(/* ... */);

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

Alternatywnie możesz przekazać własny obiekt Latte\Engine do Lintera:

$latte = new Latte\Engine;
// tutaj konfigurujemy obiekt $latte
$linter = new Latte\Tools\Linter(engine: $latte);

Ładowanie szablonów z ciągu znaków

Potrzebujesz ładować szablony z ciągów znaków zamiast plików, na przykład do celów testowania? Pomoże Ci StringLoader:

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

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

Obsługa wyjątków

Możesz zdefiniować własny handler do obsługi oczekiwanych wyjątków. Przekazane zostaną mu wyjątki powstałe wewnątrz {try} oraz w sandboxie.

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

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

Automatyczne wyszukiwanie layoutu

Za pomocą znacznika {layout} szablon określa swój szablon nadrzędny. Możliwe jest również automatyczne wyszukiwanie layoutu, co uprości pisanie szablonów, ponieważ nie będzie w nich konieczne używanie 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 pliku layoutu
		return 'automatic.layout.latte';
	}
};

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

Jeśli szablon nie ma mieć layoutu, informuje o tym znacznikiem {layout none}.