Layouts und Themen in Twig
Die Template Engine Twig bietet die Möglichkeit von Vererbung, Includes und sogar Traits. So können Blöcke in den Templates auch ohne Vererbung wiederverwendet werden. Einen möglichen Weg möchte ich hier beschreiben.
Bei Projekten, in denen die Template-Engine Twig zum Einsatz kommt, besteht unter Umständen die Herausforderung darin, dass einige oder auch mehrere Template-Bestandteile immer wieder verwendet werden sollen. Da kommt schnell die Frage auf, wie organisiere ich meine Template-Struktur?
Ein Beispiel möchte ich hier zeigen, nachdem ich auf diesen Beitrag gestoßen bin. Danach habe ich eine, für mich optimale Struktur, entwickelt. Beginnen wir mit der Ordner-Struktur innerhalb eines Symfony Projektes:
templates/
├─ components/
│ ├─ form/
│ │ └─ form-horizontal.html.twig
│ ├─ sidebars/
│ │ └─ sidebar-blog.html.twig
│ └─ alerts.html.twig
├─ emails/
│ ├─ contact.html.twig
│ └─ contact.txt.twig
├─ layouts/
│ ├─ abstracts/
│ │ ├─ boxed.html.twig
│ │ ├─ fluid.html.twig
│ │ └─ nogrid.html.twig
│ ├─ themes/
│ │ ├─ blank.html.twig
│ │ ├─ fullwidth.html.twig
│ │ ├─ sidebar-left.html.twig
│ │ └─ sidebar-right.html.twig
│ ├─ error.html.twig
│ └─ blog.html.twig
├─ modules/
│ ├─ blocks.html.twig
│ └─ macros.html.twig
├─ pages/
│ ├─ blog/
│ │ ├─ listing.html.twig
│ │ └─ single.html.twig
│ ├─ error/
│ │ ├─ 404.html.twig
│ │ └─ generic.html.twig
│ ├─ security/
│ │ └─ login.html.twig
│ └ homepage.html.twig
└─ base.html.twig
Damit ist es relativ einfach, verschiedene Templates für Unterseiten des Projektes zu erstellen. Nehmen wir zum Beispiel die Startseite einer Website. Dazu sieht die Controller Methode in etwa so aus:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends AbstractController
{
/**
* @return Response
*/
public function homepage(): Response
{
return $this->render('pages/homepage.html.twig');
}
}
Das Template templates/pages/homepage.html.twig sieht dann wie folgt aus:
{% extends "layouts/abstracts/boxed.html.twig" %}
{% block layout %}
{% embed 'layouts/themes/fullwidth.html.twig' %}
{% block content %}
<p>Homepage</p>
{% endblock %}
{% endembed %}
{% endblock %}
Wie wir sehen, wird als erstes das abstrakte Layout boxed.html.twig erweitert. Dieses definiert den Block layout
und bindet ein weiteres Thema namens fullwidth.html.twig ein. In diesem Thema wird der Block content
definiert, welchen wir dann für die Homepage überschreiben. Der Inhalt des Boxed Layouts ist Folgender:
{% extends "base.html.twig" %}
{% set template = 'container' %}
...und das Thema für die volle Breite des Bildschirms:
<div class="row">
<section class="col content">
{% block content %}{% endblock -%}
</section>
</div>
Fehlt zu guter Letzt noch die base.html.twig, welche diesen Inhalt hat.
{% use 'modules/blocks.html.twig' %}
<!doctype html>
<html lang="{{ app.request.locale }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{%- block title '' -%}</title>
{{ encore_entry_link_tags('css/app') }}
{{ encore_entry_link_tags('css/themes/'~theme|default('default')) }}
{% block stylesheets %}{% endblock -%}
</head>
<body class="{{ classes|default()|join(' ') }}" itemscope itemtype="https://schema.org/WebPage">
{{- block('header') -}}
<main class="{{ template|default('container') }}"{% if schema is defined and schema is not same as(null) %} itemscope itemtype="{{ schema }}"{% endif %}>
{% block layout %}{% endblock -%}
</main>
<footer class="container-fluid footer">
<div class="{{ template|default('container') }} text-center">
{{- block('footer') -}}
</div>
</footer>
{{ encore_entry_script_tags('js/app') }}
{% block javascripts %}{% endblock %}
</body>
</html>
Das ist recht viel Code auf einmal. Also nehmen wir das Renedering mal auseinander.
- Startpunkt ist das Template templates/pages/homepage.html.twig
- Dieses erweitert das Layout templates/layouts/abstracts/boxed.html.twig
- hier wird das Basis Template templates/base.html.twig erweitert, welches u.A. den Block
layout
definiert - Außerdem wird eine Twig Variable namens
template
mit dem Wert `container` gesetzt. Damit wird eine Bootstrap Klasse für das Grid-System gesetzt.
- hier wird das Basis Template templates/base.html.twig erweitert, welches u.A. den Block
- Weiterhin wird das Theme templates/themes/fullwidth.html.twig eingebunden
- Das Thema definiert den Block
content
, welchen wir dann auf der Homepage überschreiben können.
- Das Thema definiert den Block
- Dieses erweitert das Layout templates/layouts/abstracts/boxed.html.twig
Zusätzlich haben wir noch die Möglichkeit, wiederkehrende Bestandteile (Blöcke) zu definieren und dann mehrfach zu verwenden. In meinem Beispiel wird das Markup für den Header und Footer so generiert. Aber auch Widgets für die Sidebar sind somit möglich. Das und die Verwendung von Macros ist aber Bestandteil eines anderen Beitrags.
Leave a comment
No comments:
No comments found!