Twig: Flexibel arbeiten mit Blöcken

Durch die Arbeit mit Symfony2 lerne ich immer mehr auch die Vorteile und hohe Flexibilität von Twig zu schätzen. Es bietet einfach eine Menge Funktionen von Hause aus und lässt sich zudem auch einfach erweitern. Aber das nur am Rande.

In einem Projekt an dem ich gerade arbeite verwende ich ein Bootstrap-Grid und will gewisse Teile nur rendern, wenn sie verwendet werden bzw. Inhalte bereitstellen. Dazu müssen entsprechende Blöcke überprüft und CSS-Klassen angepasst werden.

Erstmal das Basis-Template ohne irgendwelche Anpassungen (base.html.twig):

<html>
  <head>...</head>
  <body>
    <div class="container-fluid">
      <div class="row-fluid">

        <div class="span3 sidebar-left">
        {% block sidebar_left %}{% endblock %}
        </div>

        <div class="span4 content">
        {% block content %}{% endblock %}
        </div>

        <div class="span3 sidebar-right">
        {% block sidebar_right %}{% endblock %}
        </div>

      </div>
    </div>
  </body>
</html>

Der Nachteil an diesem Konstrukt ist recht offensichtlich. Das Layout ist starr und leere Elemente würden viel Platz verschwenden. Um das zu vermeiden können wir das Template etwas intelligenter machen. Normalerweise hat Logik in Templates nichts zu suchen, aber in dem Fall geht es allein um die Anzeige.

Die Blöcke lassen sich in Variablen schreiben und dann prüfen.

{% set sbleft = block('sidebar_left') %}

{% if sbleft is not empty %}
  {# mach irgendwas #}
{% endif %}

Durch diesen einfachen Code lassen sich die einzelnen Teile im Template nun einfach steuern. Auch wenn es ein paar Zeilen Code braucht, aber das wird später vielfach wieder eingespart.

{% set sbleft = block('sidebar_left') %}
{% set sbrigth = block('sidebar_right') %}

{% if sbleft is empty and sbright is empty %}
  {% set contentClass = 'span12' %}
{% elseif sbleft is empty or sbright is empty %}
  {% set contentClass = 'span8' %}
  {% set sidebarClass = 'span4' %}
{% else %}
  {% set contentClass = 'span6' %}
  {% set sidebarClass = 'span3' %}
{% endif %}

<html>
  <head>...</head>
  <body>
    <div class="container-fluid">
      <div class="row-fluid">

        {% if sbleft is not empty %}
        <div class="{{ sidebarClass }} sidebar-left">
        {% block sidebar_left %}{% endblock %}
        </div>
        {% endif %}

        <div class="span4 content">
        {% block content %}{% endblock %}
        </div>

        {% if sbright is not empty %}
        <div class="{{ sidebarClass }} sidebar-right">
        {% block sidebar_right %}{% endblock %}
        </div>
        {% endif %}

      </div>
    </div>
  </body>
</html>

Damit  ist dieses Template nun schlau genug und weiß wann welcher Bereich angezeigt werden soll und in welcher Größe. Die Klassen für die Sidebars können auch getrennt für jede Seite vergeben werden, wenn der Aufbau nicht symetrisch sein soll.

In einem anderen Template können wir wie gewohnt damit arbeiten.

{% extends "::base.html.twig" %}

{% block content %}
Hier der Seiteninhalt.
{% endblock %}

{% block sidebar_right %}
Hier die rechte Sidebar.
{% endblock %}

Viel Spaß beim Probieren! Kommentare, Anmerkungen oder Fragen sind wie immer willkommen.

Ein Kommentar

  1. Man kann die Dinger übrigens auch verschachteln. Damit wird Dein Layout noch unendlich viel flexibler:

    {% block content_wrapper %}

    {% block content %}{% endblock %}

    {% endblock %}

Schlagwörter: Adapter, Amazon, Animation, Annotations, Anonyme Klasse, Ant, Apache, API, Array, ArrayAccess, Attachment, AutoLoader, Bedienung, Bedingung, Benchmark, Bildbearbeitung, BOM, Bootstrap, Bot, Byte Order Mark, Callback, CamelCase, Canvas, Captcha, Cheatsheet, CLI, Closure, Cloud, CodeSniffer, Community, Comparator, Contest, Controller, Converter, CouchDB, Countable, Cronjob, CSV, CustomLibrary, Custom_Model, Data Mapper, Datei, Datenbank, Datenstruktur, Datentypen, Dating, Decorator, Dekorierer, Design Patterns, Dump, Duplikat, each, Eclipse, Entwicklung, Entwurfsmuster, Enum, Erweiterung, Eventhandling, Exception-Handling, Extension, Factory, Fehler, Flash, Foreach, Formatierung, Formular, Funktion, Futon, Header, HTML5, HTTP, IDE, If, Implementierung, InnoDB, Interceptor, Interface, isset, Iterator, Java, JavaScript, jQuery, Konfiguration, Konsole, Kontrollstruktur, kopieren, Late Static Binding, Layout, Linux, Listeners, Logging, Löschen, Magento, Magic Methods, Marketing, Methode, Model, MVC, MySQL, NetBeans, Objekt, Observable, Observer, OOP, Operator, Parameter, Partnersuche, Performance, PHP, phpMyAdmin, PHPUnit, Plugin, Proxy, Qualitätssicherung, Query, Reflection, Request, Response, Rest-API, Rockstar, Routing, S3, Samba, Scheifen, Schleife, Schutz, Secure Shell, Selbstreferenz, Shop, Sicherheit, Sicherung, Singleton Pattern, SOAP, Sortierung, Sourcecode, Spam, Speicherproblem, Spickzettel, SPL, SSH, Statement, Stellvertreter, Strategy Pattern, Stream, String, Sun VirtualBox, Support, Switch, Symfony, Symfony2, Symfony Live, Tag, Template, Template Method, Ternär Operator, Testing, Thumbnail, Tool, Tour, Twig, Type-Cast, Umwandlung, Underscore, unset, Vererbung, Verzweigung, Video, Videospiel, Virtualisierung, Visitor Pattern, Vorschaubild, walk, Webserver, Webservice, Weiterleitung, Wrapper, Youtube, Zeitsteuerung, Zend Framework, Zend_Cloud, Zend_CodeGenerator, Zend_Http_Client, Zend_Service, Zugriffsmethode