Twig & Pattern Lab

Ein

 

 

Freitagsfrühstück

Twig

Twig is a modern template engine for PHP

  • Fast: Twig compiles templates down to plain optimized PHP code. 
  • Secure: Twig has a sandbox mode to evaluate untrusted template code. 
  • Flexible: Twig is powered by a flexible lexer and parser.

Twig Environment

Environment

Loader

Template Pfad(e)

Cache

Template

Output

load(string $template):Template
render(array $context):string

Twig Internals

Load

Tokenize (Lexer)

Parse into AST*

*Abstract Syntax Tree

Evaluate

Is compiled?

no
yes

Twig für Template Designer

<!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>

Delimiter

  • {% ... %} = führe Statement aus
  • {{ ... }} = gebe Statement aus

Variablen

{# gibt den Wert von foo aus, bzw. foo.toString() #}
{{ foo }} 

{{ foo.bar }}
{# ist equivalent zu #}
{{ foo['bar'] }}

{{ foo.data-foo }} # geht nicht!
{# ...das schon! #}
{{ attribute(foo, 'data-foo') }}

{# wenn foo = undefined und strict_variables = false #}
{{ foo }} {# ist null und gibt einen Leerstring aus #}

Variablen setzen

{# skalar #}
{% set foo = 'foo' %}
{# array #}
{% set foo = [1, 2] %}
{# object #}
{% set foo = {'foo': 'bar'} %}
{# blocks #}
{% set foo %}
    <div id="pagination">
        ...
    </div>
{% endset %}

{# JavaScript, anyone? #}

Filter

{# Entferne alle HTML Tags aus `name` und `title-case` es. #}
{{ name | striptags | title }}

{# Verbinde alle Elemente der Liste mit ` ,`. #}
{{ list | join(', ') }}

{# Was wohl? #}
{% filter upper %}
    Hallo Welt!
{% endfilter %}

Filter

  • abs
  • batch
  • capitalize
  • convert_encoding
  • date
  • date_modify
  • default
  • escape
  • first
  • format
  • join
  • json_encode
  • keys
  • last
  • length
  • lower
  • merge
  • nl2br
  • number_format
  • raw
  • replace
  • reverse
  • round
  • slice
  • sort
  • split
  • striptags
  • title
  • trim
  • upper
  • url_encode

Funktionen

{{ max(1, 3, 2) }}

{% set numbers = range(0, 3) %}

{{ random(5) }} 

{# Named Arguments #}
{{ data | convert_encoding('UTF-8', 'iso-2022-jp') }}

{# versus #}

{{ data | convert_encoding(from='iso-2022-jp', to='UTF-8') }}

Funktionen

  • attribute
  • block
  • constant
  • cycle
  • date
  • dump
  • include
  • max
  • min
  • parent
  • random
  • range
  • source
  • template_from_string

Kontrollstrukturen

{% if users | length > 0 %}
    {# ... tu was #}
{% endif %}

{# wenn users ein array oder Traversable ist #}
{% for user in users %}
    <li>{{ user.username }}</li>
{% endfor %}

for ... in kann mehr...

{% for user in users %}
    {{ loop.index }} - {{ user.username }}
{% endfor %}

{#
loop.index	The current iteration of the loop. (1 indexed)
loop.index0	The current iteration of the loop. (0 indexed)
loop.revindex	The number of iterations from the end of the loop (1 indexed)
loop.revindex0	The number of iterations from the end of the loop (0 indexed)
loop.first	True if first iteration
loop.last	True if last iteration
loop.length	The number of items in the sequence
loop.parent	The parent context
#}

for ... in kann noch mehr...

<ul>
    {% for user in users if user.active %}
        <li>{{ user.username }}</li>
    {% endfor %}
</ul>
<ul>
    {% for user in users %}
        <li>{{ user.username }}</li>
    {% else %}
        <li><em>no user found</em></li>
    {% endfor %}
</ul>

und

Was ist mit assoziativen Arrays?

<h1>Members</h1>
<ul>
    {# keys only #}
    {% for key in users | keys %}
        <li>{{ key }}</li>
    {% endfor %}
    {# keys and values #}
    {% for key, user in users %}
        <li>{{ key }}: {{ user.username }}</li>
    {% endfor %}
</ul>

Andere Templates inkludieren

{{ include('sidebar.html') }}
{% for box in boxes %}
    {# kennt alle Variablen des äußeren Scopes #}
    {{ include('render_box.html') }}
{% endfor %}
{% for foo in boxes %}
    {# Setzt die innere Variable box mit dem Wert von foo #}
    {{ include('render_box.html', {box: foo}) }}
{% endfor %}
{# keine äußeren Variablen sind innen vorhanden #}
{{ include('template.html', with_context = false) }}

Andere Templates inkludieren

{% include 'sidebar.html' %}
{% for box in boxes %}
    {# kennt alle Variablen des äußeren Scopes #}
    {% include 'render_box.html.twig' with {box: box} %}
{% endfor %}
{% include 'footer.html.twig' only %}
{% include 'footer.html.twig' ignore missing %}

Template inheritance

<!DOCTYPE html>
<html>
    <head>
        {% block head %}
            <link rel="stylesheet" href="style.css" />
            <title>{% block title %}{% endblock %} - My Webpage</title>
        {% endblock %}
    </head>
    <body>
        <div id="content">{% block content %}{% endblock %}</div>
        <div id="footer">
            {% block footer %}
                &copy; Copyright 2011 by <a href="http://domain.invalid/">you</a>.
            {% endblock %}
        </div>
    </body>
</html>

Template inheritance

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

{% block title %}Index{% endblock %}
{% block head %}
    {{ parent() }}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}
{% block content %}
    <h1>Index</h1>
    <p class="important">
        Welcome to my awesome homepage.
    </p>
{% endblock %}
{% block footer %}{% endblock %}

Pattern Lab

ein Styleguide und Production Tool

Was kann es?

  • definiert Elemente/Features einer Webseite
     
  • Prinzip: Atomic Design
     
  • Plugin/Extension Schnittstelle
     
  • Styleguide Übersicht aller Elemente

Pattern Lab

Warum brauche ich das?

  • strikte Trennung von Content und Layout
    (nutzt Mock/Faker Daten)
     
  • geringe Einarbeitungszeit (Styleguide)
     
  • “gibt es das Element schon?”
     
  • kann ohne Ziel Applikation umgesetzt werden
    und umgekehrt

Pattern Lab

Atomic Design

legt durch seinen modularen Aufbau den Grundstein für die Erstellung wiederverwendbarer Elemente einer Webseite... (Brad Frost)

Pattern Lab

Aufbau

Atom

Molekül

Organismus

Template

Seite

modular

Pattern Lab

Aber warum?

Pattern Lab

Reusable!

Pattern Lab

Atom

Elemente, die nicht weiter zerlegt werden.

Pattern Lab

Beispiele

  • <input> / <img> / <label>
     
  • Preis (Float Wert formatiert mit Währung)

Atom

Pattern Lab

Molekül

  • setzt sich aus Atomen zusammen.
     
  • "Mach-eine-Sache-und-mach-sie-gut“-Strategie.
     
  • Man erkennt bereits, welche Funktionalität gemeint ist.

Pattern Lab

Beispiele

  • Link (enthält: label, img, etc.)
     
  • Suchschlitz Formular
     
  • Content Box (Titel und Text)

Molekül

Pattern Lab

Organismus

  • Setzt sich aus Molekülen zusammen.
     
  • Bildet komplette Bereiche einer Seite

Pattern Lab

Beispiele

  • Seite Kopfbereich
     
  • Produktkachel (Bild(Link mit img), Label, Produktpreis(Preis), Streichpreis(Preis))
     
  • Produktliste (Produktkacheln)

Organismus

Pattern Lab

Template

  • Fasst Organismen zusammen.
     
  • Zeigt bereits einen Großteil der Oberfläche

Pattern Lab

Beispiele

  • Kategorie Ansicht/Feature
    (Header, Liste der Unterkategorien, Produktliste)

     
  • Dashboard Feature

Kundenaufmerksamkeit beginnt oft hier

Template

Pattern Lab

Seite

  • Instanzen von Templates.
     
  • Mock/Faker-Inhalten erwecken das Design zum Leben
     
  • offenbaren Layout/Inhalts Schwierigkeiten
    (lange Texte, sich ändernde Bildformate, etc.)

Pattern Lab

Wie sieht das aus?

Pattern Lab

Styleguide View

Pattern Lab

Templates

/Patternlab
  /source
    /_patterns
      /00-atoms
        /10-button.json
        /10-button.twig

Pattern Lab

10-button.json

10-button.twig

{
  "button": {
    "label": "Senden",
    "class": "",
    "layout": "primary",
    "type": "submit"
  }
}
<button type="{{ button.type }}" 
     class="[ btn btn-{{ button.layout }} ] {{ button.class }}" 
>{{ button.label }}</button>

Mock Daten

Pattern Lab

Wohin geht es hier aus?

  • Twig Template Extension / Namespaces
     
  • Data Transfer Objects (DTO)
     
  • Resourcen Management
     
  • Deployment von Templates

Pattern Lab

Twig & Patternlab

By Ole Rößner

Twig & Patternlab

  • 1,095