Twig Template Engine

Einleitung

Twig ist eine Template-Sprache, die eng an das Symfony Framework gekoppelt ist. Es ist aber auch möglich diese allein stehend zu verwenden. Sie erlaubt uns HTML Markup zu schreiben und durch eine eigene Syntax einzelne Bereiche dynamisch zu gestalten.

Verwendung von Twig

Für Twig Templates gibt es ein extra Verzeichnis, in dem alle Templates liegen: <customer-project>/<customer>-module/src/publish/php/templates (Für neue Module, bei denen PHP Code in einem eigenen GIT Projekt liegt, ist es php/templates). In diesem Ordner können nach Belieben, weitere Unterordner und Strukturen erstellt werden. Für Twig Templates muss immer die Dateiendung .twig verwendet werden.

Wie im folgenden Beispiel zu sehen, ist Twig für Web Entwickler einfach zu lesen und bietet gleichzeitig mehr flexibilität:

<!DOCTYPE html>
<html>
    <head>
        <title>My Webpage</title>
    </head>
    <body>
        <ul id="navigation">
        {% for item in navigation %}
            <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
        {% endfor %}
        </ul>

        <h1>My Webpage</h1>
        {{ a_variable }}
    </body>
</html>

Weitere Informationen über die Syntax, Funktionen und Filter, gibt es in der offiziellen Twig Dokumentation.

Integration in Kundenmodulen

Twig kann optional in einem Modul verwendet werden und ist in wenigen Schritten einsatzbereit. Da die Basis schon im SiteKit integriert ist, muss in einem (Kunden)Modul nur der Ordner mit den Templates bekannt gemacht werden:

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
		   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		   xsi:schemaLocation="http://symfony.com/schema/dic/services
	https://symfony.com/schema/dic/services/services-1.0.xsd">

	<services>

		<service id="twig.loader.bonn.filesystem" class="Twig\Loader\FilesystemLoader" autoconfigure="false" autowire="false">
			<tag name="twig.loader"/>
			<call method="addPath">
				<argument>%sitekit.module_source%/../bonn-module/php/templates</argument>
				<argument>bonn-module</argument>
			</call>
		</service>
	</services>
</container>

Dieses Beispiel zeigt die Integration für das Bonn Modul. Daher müssen die Argumente entsprechend angepasst werden. Erstes Argument: Dies ist der Pfad zu dem Ordner, in dem alle Templates enthalten sind. das %sitekit.module_source% ist eine Variable, die auf den SiteKit Ordner verweist. Ausgehend von diesem Ordner muss der Pfad auf den Templates Ordner verwiesen werden.

Zweites Argument: Dies ist ein Namensraum für die Templates. Damit ist es möglich, auch auf andere Templates zu verweisen. Mit dem Template Pfad @sitekit/html.twig würde bspw. ein Template aus dem SiteKit Modul gerendert werden. Allerdings muss dafür gesorgt sein, dass dieses auch existiert. Wird ein Template nicht gefunden, gibt es eine Exception.

Damit wir in einem Renderer auch auf Twig zugreifen können, muss noch ein Service im Dependency Injection Container eingetragen werden:

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
		   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		   xsi:schemaLocation="http://symfony.com/schema/dic/services
	https://symfony.com/schema/dic/services/services-1.0.xsd">

	<services>
		<defaults autowire="true" autoconfigure="true"/>

		<service id="renderer.bonn.audio" class="SP\Bonn\Renderer\Audio" public="true">
			<factory class="SP\SiteKit\Renderer\TemplateFactory" method="createTemplate"/>
			<argument type="string">\SP\Bonn\Renderer\Audio</argument>
			<argument type="service" id="twig"/>
			<argument type="service" id="sp.sitekit.renderer.renderer_context.html"/>
			<argument type="service" id="component_model.html"/>
		</service>
	</service>
</container>

Damit wird der Renderer aus dem Symfony Dependency Injection Container geholt und in der Factory wird Twig über setEnvironment an den Renderer übergeben. Somit kann die Template Engine verwendet werden:

<?php declare(strict_types=1);

namespace SP\Bonn\Renderer;

use SP\SiteKit\Renderer\Renderer;
use Twig\Environment;

/**
 * @method \SP\SiteKit\Model\Audio\Audio getModel()
 */
class Audio extends Renderer {

	public const TYPE = 'html.arvedui.content.audio.audio';

	private const TEMPLATE = '@bonn-module/audio.twig';

	/** @var Environment */
	private $engine;

	public function setEnvironment(Environment $environment) {
		$this->engine = $environment;
	}

	public function render(): void {
		$this->engine->display(self::TEMPLATE, ['model' => $this->getModel()]);
	}
}