-
-
Notifications
You must be signed in to change notification settings - Fork 276
Expand file tree
/
Copy pathdevelop.texy
More file actions
355 lines (244 loc) · 14.2 KB
/
develop.texy
File metadata and controls
355 lines (244 loc) · 14.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
Entwicklerpraktiken
*******************
Installation
============
Der beste Weg, Latte zu installieren, ist über Composer:
```shell
composer require latte/latte
```
Unterstützte PHP-Versionen (gilt für die letzten Patch-Versionen von Latte):
| Version | Kompatibel mit PHP
|-----------------|-------------------
| Latte 3.0 | PHP 8.0 – 8.2
Wie rendert man ein Template?
=============================
Wie rendert man ein Template? Dafür genügt dieser einfache Code:
```php
$latte = new Latte\Engine;
// Verzeichnis für den Cache
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* Template-Variablen */ ];
// oder $params = new TemplateParameters(/* ... */);
// in die Ausgabe rendern
$latte->render('template.latte', $params);
// in eine Variable rendern
$output = $latte->renderToString('template.latte', $params);
```
Parameter können Arrays sein oder noch besser [ein Objekt |#Parameter als Klasse], das Typprüfung und Autovervollständigung in Editoren sicherstellt.
.[note]
Anwendungsbeispiele finden Sie auch im Repository [Latte examples |https://github.com/nette-examples/latte].
Leistung und Cache
==================
Templates in Latte sind extrem schnell, da Latte sie direkt in PHP-Code kompiliert und auf der Festplatte zwischenspeichert. Sie haben also keinen zusätzlichen Overhead gegenüber Templates, die in reinem PHP geschrieben sind.
Der Cache wird automatisch jedes Mal neu generiert, wenn Sie die Quelldatei ändern. Während der Entwicklung können Sie also bequem Ihre Latte-Templates bearbeiten und die Änderungen sofort im Browser sehen. Sie können diese Funktion in der Produktionsumgebung deaktivieren, um ein wenig Leistung zu sparen:
```php
$latte->setAutoRefresh(false);
```
Bei der Bereitstellung auf einem Produktionsserver kann die anfängliche Generierung des Caches, insbesondere bei größeren Anwendungen, natürlich einen Moment dauern. Latte verfügt über eine integrierte Prävention gegen "Cache Stampede":https://en.wikipedia.org/wiki/Cache_stampede. Dies ist eine Situation, in der eine größere Anzahl gleichzeitiger Anfragen eintrifft, die Latte starten, und da der Cache noch nicht existiert, würden sie alle gleichzeitig mit der Generierung beginnen. Dies würde den Server unverhältnismäßig belasten. Latte ist intelligent und bei mehreren gleichzeitigen Anfragen generiert nur der erste Thread den Cache, die anderen warten und nutzen ihn anschließend.
Parameter als Klasse
====================
Besser als Variablen als Array an das Template zu übergeben, ist es, eine Klasse zu erstellen. Sie erhalten so eine [typsichere Schreibweise |type-system], [angenehme Autovervollständigung in IDEs |recipes#Editoren und IDEs] und einen Weg zur [Registrierung von Filtern |custom-filters#Filter unter Verwendung einer Klasse mit Attributen] und [Funktionen |custom-functions#Funktionen unter Verwendung einer Klasse mit Attributen].
```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,
));
```
Deaktivieren des automatischen Escapings einer Variablen
========================================================
Wenn eine Variable eine Zeichenkette in HTML enthält, können Sie sie so markieren, dass Latte sie nicht automatisch (und somit doppelt) escapet. Sie vermeiden so die Notwendigkeit, `|noescape` im Template anzugeben.
Der einfachste Weg ist, die Zeichenkette in ein `Latte\Runtime\Html`-Objekt zu verpacken:
```php
$params = [
'articleBody' => new Latte\Runtime\Html($article->htmlBody),
];
```
Latte escapet außerdem keine Objekte, die das Interface `Latte\HtmlStringable` implementieren. Sie können also eine eigene Klasse erstellen, deren `__toString()`-Methode HTML-Code zurückgibt, der nicht automatisch escapet wird:
```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]
Die `__toString`-Methode muss korrektes HTML zurückgeben und das Escaping von Parametern sicherstellen, andernfalls kann eine XSS-Schwachstelle entstehen!
Wie erweitert man Latte um Filter, Tags usw.?
=============================================
Wie fügt man Latte eigene Filter, Funktionen, Tags usw. hinzu? Dies wird im Kapitel [Latte erweitern |extending-latte] behandelt. Wenn Sie Ihre Anpassungen in verschiedenen Projekten wiederverwenden oder mit anderen teilen möchten, sollten Sie [eine Erweiterung erstellen |extending-latte#Latte Extension].
Beliebiger Code im Template `{php ...}` .{toc: RawPhpExtension}
===============================================================
Innerhalb des Tags [`{do}` |tags#do] können nur PHP-Ausdrücke geschrieben werden, Sie können also keine Konstrukte wie `if ... else` oder Anweisungen, die mit einem Semikolon enden, einfügen.
Sie können jedoch die Erweiterung `RawPhpExtension` registrieren, die das Tag `{php ...}` hinzufügt. Damit können Sie beliebigen PHP-Code einfügen. Für ihn gelten keine Sandbox-Regeln, die Verwendung liegt also in der Verantwortung des Template-Autors.
```php
$latte->addExtension(new Latte\Essential\RawPhpExtension);
```
Überprüfung des generierten Codes .{data-version:3.0.7}
=======================================================
Latte kompiliert Templates in PHP-Code. Natürlich achtet es darauf, dass der generierte Code syntaktisch valide ist. Bei Verwendung von Drittanbieter-Erweiterungen oder `RawPhpExtension` kann Latte jedoch die Korrektheit der generierten Datei nicht garantieren. Außerdem kann man in PHP Code schreiben, der zwar syntaktisch korrekt ist, aber verboten ist (z. B. Zuweisung eines Wertes zur Variablen `$this`) und einen PHP Compile Error verursacht. Wenn Sie eine solche Operation im Template schreiben, gelangt sie auch in den generierten PHP-Code. Da es in PHP über zweihundert verschiedene verbotene Operationen gibt, hat Latte nicht den Ehrgeiz, sie alle aufzudecken. PHP selbst weist erst beim Rendern darauf hin, was normalerweise kein Problem darstellt.
Es gibt jedoch Situationen, in denen Sie bereits zur Kompilierungszeit des Templates wissen möchten, dass es keinen PHP Compile Error enthält. Insbesondere dann, wenn Templates von Benutzern bearbeitet werden können oder Sie die [Sandbox |sandbox] verwenden. In diesem Fall lassen Sie die Templates bereits zur Kompilierungszeit überprüfen. Diese Funktionalität aktivieren Sie mit der Methode `Engine::enablePhpLint()`. Da zur Überprüfung die PHP-Binärdatei aufgerufen werden muss, übergeben Sie den Pfad dorthin als Parameter:
```php
$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
try {
$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
// fängt Fehler in Latte und auch Compile Errors in PHP ab
echo 'Fehler: ' . $e->getMessage();
}
```
Gebietsschema .{data-version:3.0.18}{toc: Locale}
=================================================
Latte ermöglicht die Einstellung des Gebietsschemas, das die Formatierung von Zahlen, Daten und die Sortierung beeinflusst. Sie wird mit der Methode `setLocale()` eingestellt. Der Gebietsschema-Bezeichner folgt dem IETF-Sprach-Tag-Standard, der von der PHP-Erweiterung `intl` verwendet wird. Er besteht aus dem Sprachcode und optional dem Ländercode, z. B. `en_US` für Englisch in den Vereinigten Staaten, `de_DE` für Deutsch in Deutschland usw.
```php
$latte = new Latte\Engine;
$latte->setLocale('de_DE');
```
Die Gebietsschema-Einstellung beeinflusst die Filter [localDate |filters#localDate], [sort |filters#sort], [number |filters#number] und [bytes |filters#bytes].
.[note]
Erfordert die PHP-Erweiterung `intl`. Die Einstellung in Latte beeinflusst nicht die globale Locale-Einstellung in PHP.
Strikter Modus .{data-version:3.0.8}
====================================
Im strikten Parsing-Modus prüft Latte, ob schließende HTML-Tags fehlen und verbietet außerdem die Verwendung der Variablen `$this`. Sie aktivieren ihn so:
```php
$latte = new Latte\Engine;
$latte->setStrictParsing();
```
Die Generierung von Templates mit dem Header `declare(strict_types=1)` aktivieren Sie so:
```php
$latte = new Latte\Engine;
$latte->setStrictTypes();
```
Übersetzung in Templates .{toc: TranslatorExtension}
====================================================
Mit der Erweiterung `TranslatorExtension` fügen Sie dem Template die Tags [`{_...}` |tags#], [`{translate}` |tags#translate] und den Filter [`translate` |filters#translate] hinzu. Sie dienen zur Übersetzung von Werten oder Teilen des Templates in andere Sprachen. Als Parameter geben wir eine Methode (PHP callable) an, die die Übersetzung durchführt:
```php
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// aus $original erstellen wir $translated gemäß $this->lang
return $translated;
}
}
$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...), // [$translator, 'translate'] in PHP 8.0
);
$latte->addExtension($extension);
```
Der Translator wird zur Laufzeit beim Rendern des Templates aufgerufen. Latte kann jedoch alle statischen Texte bereits während der Kompilierung des Templates übersetzen. Dadurch wird Leistung gespart, da jede Zeichenkette nur einmal übersetzt wird und die resultierende Übersetzung in die kompilierte Form geschrieben wird. Im Cache-Verzeichnis entstehen so mehrere kompilierte Versionen des Templates, eine für jede Sprache. Dazu genügt es, die Sprache als zweiten Parameter anzugeben:
```php
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
```
Statischer Text bedeutet z. B. `{_'hello'}` oder `{translate}hello{/translate}`. Nicht-statische Texte, wie z. B. `{_$foo}`, werden weiterhin zur Laufzeit übersetzt.
Dem Übersetzer können aus dem Template auch zusätzliche Parameter übergeben werden, mittels `{_$original, foo: bar}` oder `{translate foo: bar}`, die er als Array `$params` erhält:
```php
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
```
Debugging und Tracy
===================
Latte versucht Ihnen die Entwicklung so angenehm wie möglich zu gestalten. Direkt für Debugging-Zwecke gibt es drei Tags: [`{dump}` |tags#dump], [`{debugbreak}` |tags#debugbreak] und [`{trace}` |tags#trace].
Den größten Komfort erhalten Sie, wenn Sie zusätzlich das hervorragende [Debugging-Werkzeug Tracy |tracy:] installieren und das Add-on für Latte aktivieren:
```php
// schaltet Tracy ein
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// aktiviert die Erweiterung für Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
```
Nun werden Ihnen alle Fehler in einem übersichtlichen roten Bildschirm angezeigt, einschließlich Fehlern in Templates mit Hervorhebung von Zeile und Spalte ([Video |https://github.com/nette/tracy/releases/tag/v2.9.0]). Gleichzeitig erscheint unten rechts in der sogenannten Tracy Bar ein Tab für Latte, wo alle gerenderten Templates und ihre gegenseitigen Beziehungen übersichtlich dargestellt werden (einschließlich der Möglichkeit, zum Template oder zum kompilierten Code durchzuklicken) sowie die Variablen:
[* latte-debugging.webp *]
Da Latte Templates in übersichtlichen PHP-Code kompiliert, können Sie sie bequem in Ihrer IDE schrittweise debuggen.
Linter: Syntaxvalidierung von Templates .{toc: Linter}
======================================================
Um alle Templates durchzugehen und zu überprüfen, ob sie Syntaxfehler enthalten, hilft Ihnen das Werkzeug Linter. Es wird von der Konsole aus gestartet:
```shell
vendor/bin/latte-lint <pfad>
```
Mit dem Parameter `--strict` aktivieren Sie den [strikten Modus |#Strikter Modus].
Wenn Sie eigene Tags verwenden, erstellen Sie sich auch eine eigene Version des Linters, z. B. `custom-latte-lint`:
```php
#!/usr/bin/env php
<?php
// Geben Sie den tatsächlichen Pfad zur Datei autoload.php an
require __DIR__ . '/vendor/autoload.php';
$path = $argv[1] ?? '.';
$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// hier fügen Sie Ihre einzelnen Erweiterungen hinzu
$latte->addExtension(/* ... */);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);
```
Alternativ können Sie ein eigenes `Latte\Engine`-Objekt an den Linter übergeben:
```php
$latte = new Latte\Engine;
// hier konfigurieren wir das Objekt $latte
$linter = new Latte\Tools\Linter(engine: $latte);
```
Laden von Templates aus einer Zeichenkette
==========================================
Müssen Sie Templates aus Zeichenketten anstelle von Dateien laden, z. B. zu Testzwecken? Der [StringLoader |loaders#StringLoader] hilft Ihnen dabei:
```php
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file', $params);
```
Exception Handler
=================
Sie können einen eigenen Handler für erwartete Ausnahmen definieren. Ihm werden Ausnahmen übergeben, die innerhalb von [`{try}` |tags#try] und in der [Sandbox |sandbox] entstehen.
```php
$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
$logger->log($e);
};
$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);
```
Automatisches Suchen des Layouts
================================
Mit dem Tag [`{layout}` |template-inheritance#Layout-Vererbung] bestimmt ein Template sein übergeordnetes Template. Es ist auch möglich, das Layout automatisch suchen zu lassen, was das Schreiben von Templates vereinfacht, da das Tag `{layout}` darin nicht notwendig ist.
Dies wird auf folgende Weise erreicht:
```php
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// gibt den Pfad zur Layout-Datei zurück
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
```
Wenn ein Template kein Layout haben soll, teilt es dies mit dem Tag `{layout none}` mit.