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.

Suche nach Templates

Der Pfad zu den Vorlagen wird nach einer einfachen Logik hergeleitet. Es wird versucht zu sehen, ob eine dieser Vorlagendateien relativ zu dem Verzeichnis existiert, in dem sich die Presenter-Klasse befindet, wobei <Presenter> der Name des aktuellen Präsentators ist und <view> der Name der aktuellen Aktion ist:

  • templates/<Presenter>/<view>.latte
  • templates/<Presenter>.<view>.latte

Wird die Vorlage nicht gefunden, wird versucht, im Verzeichnis templates eine Ebene höher zu suchen, d. h. auf der gleichen Ebene wie das Verzeichnis mit der Presenter-Klasse.

Wenn die Vorlage auch dort nicht gefunden wird, ist die Antwort ein 404-Fehler.

Sie können die Ansicht auch mit $this->setView('otherView') ändern. Oder geben Sie statt der Suche direkt den Namen der Vorlagendatei mit $this->template->setFile('/path/to/template.latte') an.

Sie können die Pfade, in denen Vorlagen gesucht werden, ändern, indem Sie die Methode formatTemplateFiles überschreiben, die ein Array mit möglichen Dateipfaden zurückgibt.

Das Layout wird in den folgenden Dateien erwartet:

  • templates/<Presenter>/@<layout>.latte
  • templates/<Presenter>.@<layout>.latte
  • templates/@<layout>.latte gemeinsames Layout für mehrere Präsentatoren

<Presenter> ist der Name des aktuellen Präsentators und <layout> ist der Name des Layouts, der standardmäßig 'layout' lautet. Der Name kann mit $this->setLayout('otherLayout') geändert werden, so dass @otherLayout.latte Dateien ausprobiert werden.

Sie können auch direkt den Dateinamen der Layoutvorlage mit $this->setLayout('/path/to/template.latte') angeben. Durch die Verwendung von $this->setLayout(false) wird die Layout-Suche deaktiviert.

Sie können die Pfade, in denen Vorlagen gesucht werden, ändern, indem Sie die Methode formatLayoutTemplateFiles überschreiben, die ein Array mit möglichen Dateipfaden 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\Presenters\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 Nachrichten flashMessage()

Wenn Sie eine benutzerdefinierte Vorlagenklasse verwenden, werden diese Variablen übergeben, wenn Sie eine Eigenschaft für sie erstellen.

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\Templating;

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\Templating\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

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.

Version: 4.0