Vorlagen
Nette verwendet das Vorlagensystem Latte. Latte wird verwendet, weil es das sicherste Vorlagensystem für PHP und gleichzeitig das intuitivste System ist. Sie müssen nicht viel Neues lernen, Sie müssen nur PHP und ein paar Latte-Tags kennen.
In der Regel wird die Seite aus der Layout-Vorlage und der Aktionsvorlage erstellt. So könnte eine Layout-Vorlage aussehen,
beachten Sie die Blöcke {block}
und den Tag {include}
:
<!DOCTYPE html>
<html>
<head>
<title>{block title}My App{/block}</title>
</head>
<body>
<header>...</header>
{include content}
<footer>...</footer>
</body>
</html>
Und dies könnte die Aktionsvorlage sein:
{block title}Homepage{/block}
{block content}
<h1>Homepage</h1>
...
{/block}
Sie definiert den Block content
, der anstelle von {include content}
in das Layout eingefügt wird,
und definiert auch den Block title
neu, der {block title}
im Layout überschreibt. Versuchen Sie, sich
das Ergebnis vorzustellen.
Vorlage nachschlagen
In Presentern müssen Sie nicht angeben, welche Vorlage gerendert werden soll; das Framework bestimmt den Pfad automatisch, was die Codierung für Sie einfacher macht.
Wenn Sie eine Verzeichnisstruktur verwenden, in der jeder Präsentator sein eigenes Verzeichnis hat, legen Sie die Vorlage
einfach in diesem Verzeichnis unter dem Namen der Aktion (d. h. der Ansicht) ab. Verwenden Sie zum Beispiel für die Aktion
default
die Vorlage default.latte
:
app/ └── UI/ └── Home/ ├── HomePresenter.php └── default.latte
Wenn Sie eine Struktur verwenden, bei der sich die Präsentatoren in einem Verzeichnis und die Vorlagen in einem Ordner
templates
befinden, speichern Sie sie entweder in einer Datei <Presenter>.<view>.latte
oder
<Presenter>/<view>.latte
:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── Home.default.latte ← 1st variant └── Home/ └── default.latte ← 2nd variant
Das Verzeichnis templates
kann auch eine Ebene höher platziert werden, auf derselben Ebene wie das Verzeichnis
mit den Presenter-Klassen.
Wenn die Vorlage nicht gefunden wird, antwortet der Präsentator mit dem Fehler 404 – Seite nicht gefunden.
Sie können die Ansicht mit $this->setView('anotherView')
ändern. Es ist auch möglich, die Vorlagendatei
direkt mit $this->template->setFile('/path/to/template.latte')
anzugeben.
Dateien, in denen Vorlagen gesucht werden, können durch Überschreiben der Methode formatTemplateFiles() geändert werden, die ein Array mit möglichen Dateinamen zurückgibt.
Layout-Vorlagen-Suche
Nette sucht auch automatisch nach der Layout-Datei.
Wenn Sie eine Verzeichnisstruktur verwenden, in der jeder Präsentator sein eigenes Verzeichnis hat, legen Sie das Layout entweder in dem Ordner mit dem Präsentator ab, wenn es nur für diesen spezifisch ist, oder eine Ebene höher, wenn es für mehrere Präsentatoren gemeinsam ist:
app/ └── UI/ ├── @layout.latte ← common layout └── Home/ ├── @layout.latte ← only for Home presenter ├── HomePresenter.php └── default.latte
Wenn Sie eine Struktur verwenden, bei der die Vortragenden in einem Verzeichnis zusammengefasst sind und sich die Vorlagen in
einem Ordner templates
befinden, wird das Layout an den folgenden Stellen erwartet:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── @layout.latte ← common layout ├── Home.@layout.latte ← only for Home, 1st variant └── Home/ └── @layout.latte ← only for Home, 2nd variant
Befindet sich der Präsentator in einem Modul, wird er auch weiter oben im Verzeichnisbaum entsprechend der Verschachtelung des Moduls gesucht.
Der Name des Layouts kann mit $this->setLayout('layoutAdmin')
geändert werden und wird dann in der Datei
@layoutAdmin.latte
erwartet. Sie können die Layout-Vorlagendatei auch direkt mit
$this->setLayout('/path/to/template.latte')
angeben.
Die Verwendung von $this->setLayout(false)
oder des Tags {layout none}
innerhalb der Vorlage
deaktiviert die Layout-Suche.
Die Dateien, in denen Layoutvorlagen gesucht werden, können durch Überschreiben der Methode formatLayoutTemplateFiles() geändert werden, die ein Array mit möglichen Dateinamen zurückgibt.
Variablen in der Vorlage
Variablen werden an die Vorlage übergeben, indem sie in $this->template
geschrieben werden, und sind dann in
der Vorlage als lokale Variablen verfügbar:
$this->template->article = $this->articles->getById($id);
Auf diese Weise können wir problemlos beliebige Variablen an die Vorlagen übergeben. Bei der Entwicklung robuster Anwendungen ist es jedoch oft sinnvoller, sich einzuschränken. Zum Beispiel durch die explizite Definition einer Liste von Variablen, die die Vorlage erwartet, und deren Typen. Auf diese Weise kann PHP eine Typüberprüfung durchführen, die IDE eine korrekte Autovervollständigung vornehmen und die statische Analyse Fehler erkennen.
Und wie definieren wir eine solche Aufzählung? Einfach in Form einer Klasse und ihrer Eigenschaften. Wir nennen sie ähnlich
wie presenter, aber mit Template
am Ende:
/**
* @property-read ArticleTemplate $template
*/
class ArticlePresenter extends Nette\Application\UI\Presenter
{
}
class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
{
public Model\Article $article;
public Nette\Security\User $user;
// und andere Variablen
}
Das Objekt $this->template
im Presenter wird nun eine Instanz der Klasse ArticleTemplate
sein. PHP
wird also die deklarierten Typen überprüfen, wenn sie geschrieben werden. Und ab PHP 8.2 wird auch vor dem Schreiben in eine
nicht existierende Variable gewarnt. In früheren Versionen kann dasselbe mit der Nette\SmartObject-Eigenschaft erreicht werden.
Die @property-read
Annotation ist für die IDE und die statische Analyse, sie sorgt dafür, dass die
Autovervollständigung funktioniert, siehe PhpStorm and code completion for
$this->template.
Sie können sich auch den Luxus gönnen, in Vorlagen zu flüstern. Installieren Sie einfach das Latte-Plugin in PhpStorm und geben Sie den Klassennamen am Anfang der Vorlage an, siehe den Artikel Latte: how to type system:
{templateType App\UI\Article\ArticleTemplate}
...
So funktionieren Templates auch in Komponenten, folgen Sie einfach der Namenskonvention und erstellen Sie eine Template-Klasse
FifteenTemplate
für die Komponente, z.B. FifteenControl
.
Wenn Sie eine $template
als Instanz einer anderen Klasse erstellen müssen, verwenden Sie die Methode
createTemplate()
:
public function renderDefault(): void
{
$template = $this->createTemplate(SpecialTemplate::class);
$template->foo = 123;
// ...
$this->sendTemplate($template);
}
Standard-Variablen
Presenter und Komponenten übergeben automatisch mehrere nützliche Variablen an Vorlagen:
$basePath
ist ein absoluter URL-Pfad zum Stammverzeichnis (z. B./CD-collection
)$baseUrl
ist eine absolute URL zum Stammverzeichnis (z. B.http://localhost/CD-collection
)$user
ist ein Objekt , das den Benutzer repräsentiert$presenter
ist der aktuelle Präsentator$control
ist die aktuelle Komponente oder der aktuelle Präsentator$flashes
Liste der von der Methode gesendeten NachrichtenflashMessage()
Wenn Sie eine benutzerdefinierte Vorlagenklasse verwenden, werden diese Variablen übergeben, wenn Sie eine Eigenschaft für sie erstellen.
Erstellen von Links
In der Vorlage erstellen wir Links zu anderen Präsentatoren und Aktionen wie folgt:
<a n:href="Product:show">detail</a>
Das Attribut n:href
ist sehr praktisch für HTML-Tags <a>
. Wenn wir den Link an anderer Stelle,
zum Beispiel im Text, ausgeben wollen, verwenden wir {link}
:
URL is: {link Home:default}
Weitere Informationen finden Sie unter Links erstellen.
Benutzerdefinierte Filter, Tags, etc.
Das Latte-Vorlagensystem kann mit benutzerdefinierten Filtern, Funktionen, Tags usw. erweitert werden. Dies kann direkt in der
render<View>
oder beforeRender()
Methode erfolgen:
public function beforeRender(): void
{
// Hinzufügen eines Filters
$this->template->addFilter('foo', /* ... */);
// oder das Latte\Engine-Objekt direkt konfigurieren
$latte = $this->template->getLatte();
$latte->addFilterLoader(/* ... */);
}
Latte Version 3 bietet einen fortgeschritteneren Weg, indem es eine Erweiterung für jedes Webprojekt erstellt. Hier ist ein grobes Beispiel für eine solche Klasse:
namespace App\UI\Accessory;
final class LatteExtension extends Latte\Extension
{
public function __construct(
private App\Model\Facade $facade,
private Nette\Security\User $user,
// ...
) {
}
public function getFilters(): array
{
return [
'timeAgoInWords' => $this->filterTimeAgoInWords(...),
'money' => $this->filterMoney(...),
// ...
];
}
public function getFunctions(): array
{
return [
'canEditArticle' =>
fn($article) => $this->facade->canEditArticle($article, $this->user->getId()),
// ...
];
}
// ...
}
Wir registrieren sie mit configuration:
latte:
extensions:
- App\UI\Accessory\LatteExtension
Übersetzen
Wenn Sie eine mehrsprachige Anwendung programmieren, werden Sie wahrscheinlich einen Teil des Textes in der Vorlage in
verschiedenen Sprachen ausgeben müssen. Zu diesem Zweck definiert das Nette Framework eine Übersetzungsschnittstelle Nette\Localization\Translator, die über eine
einzige Methode translate()
verfügt. Diese akzeptiert die Nachricht $message
, bei der es sich in der
Regel um eine Zeichenkette handelt, und beliebige andere Parameter. Die Aufgabe besteht darin, die übersetzte Zeichenkette
zurückzugeben. Es gibt keine Standardimplementierung in Nette, Sie können nach Ihren Bedürfnissen aus mehreren fertigen
Lösungen wählen, die Sie auf Componette finden. Die Dokumentation
erklärt Ihnen, wie Sie den Übersetzer konfigurieren können.
Vorlagen können mit einem Übersetzer eingerichtet werden, den wir
mit der Methode setTranslator()
an uns übergeben:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator);
}
Alternativ kann der Übersetzer auch über die Konfiguration eingestellt werden:
latte:
extensions:
- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
Der Übersetzer kann dann z.B. als Filter |translate
verwendet werden, wobei zusätzliche Parameter an die Methode
translate()
übergeben werden (siehe foo, bar
):
<a href="basket">{='Basket'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>
Oder als Unterstrich-Tag:
<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>
Für die Übersetzung von Vorlagenabschnitten gibt es ein gepaartes Tag {translate}
(seit Latte 2.11, vorher wurde
das Tag {_}
verwendet):
<a href="order">{translate}Order{/translate}</a>
<a href="order">{translate foo, bar}Order{/translate}</a>
Der Translator wird standardmäßig zur Laufzeit beim Rendern der Vorlage aufgerufen. Latte Version 3 kann jedoch den gesamten statischen Text während der Kompilierung der Vorlage übersetzen. Dies spart Leistung, da jede Zeichenkette nur einmal übersetzt wird und die resultierende Übersetzung in das kompilierte Formular geschrieben wird. Dadurch werden mehrere kompilierte Versionen der Vorlage im Cache-Verzeichnis erstellt, eine für jede Sprache. Dazu müssen Sie nur die Sprache als zweiten Parameter angeben:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator, $lang);
}
Unter statischem Text verstehen wir z. B. {_'hello'}
oder {translate}hello{/translate}
.
Nicht-statischer Text, wie z. B. {_$foo}
, wird weiterhin im laufenden Betrieb kompiliert.