Twig 4.0 Alpha: Die neue for-Loop-Maschinerie
Twig besteht seit 17 Jahren. Die for-Schleife in Twig war in diesen 17 Jahren eine der stabilsten Konstanten des PHP-Template-Ökosystems. Sie war auch eine der subtilsten Fehlerquellen: loop.last funktionierte nicht zuverlässig mit Generatoren, for...if-Bedingungen wurden in Twig 3.0 ersatzlos gestrichen, und loop.length auf einem nicht-zählbaren Iterator lieferte leise leere Ausgaben, statt einen klaren Fehler zu werfen. Twig 4.0 baut die gesamte Loop-Maschinerie neu.
Was Sie in 8 Minuten erfahren:
- Was Fabien Potencier mit "I rebuilt the whole loop machinery" konkret meint und was das für Template-Autoren bedeutet
- Welche Breaking Changes Twig 4.0 wirklich mitbringt und welche Entwarnung gilt
- Was Extension-Autoren jetzt prüfen müssen und wie der Upgrade-Pfad von 3.x auf 4.0 aussieht
Twig 4.0.0-alpha1 wurde am 17. Mai 2026 veröffentlicht. PHP 8.2 ist das Minimum. Die Alpha ist für Production noch nicht empfohlen, aber für Testing und Extension-Autoren ab sofort relevant. Fabien Potencier hat die Änderungen in zwei Blog-Posts auf symfony.com dokumentiert: "New in Symfony 8.1: A New for Loop for Twig 4.0" und "New in Twig 4.0: Expression Parsers". Dieser Artikel fasst zusammen, was für Symfony-Teams und Agenturen wichtig ist.
Twig 4.0 Alpha: Was ändert sich?
Bereich | Was ändert sich | Betrifft | Migrationsbedarf |
|---|---|---|---|
for-Schleife (Loop-Maschinerie) | Kompletter Rebuild, Look-Ahead-Mechanismus | Alle Templates mit for | Keine Deprecations auf 3.x |
loop.last mit Iteratoren | Funktioniert jetzt mit Generatoren und Traversables | Generator-basierte Loops | Kein Handlungsbedarf |
for...if-Bedingung | Zurückgekehrt (in 3.0 entfernt) | Template-Autoren | Kein Handlungsbedarf |
loop.length/revindex auf non-countable | Wirft jetzt klaren Error statt leerer Ausgabe | Alle die loop.length nutzen | Templates prüfen |
Expression-Parser (getOperators()) | Entfällt, neue API: getExpressionParsers() | Extension-Autoren mit eigenen Operatoren | Extension-Code anpassen |
Sandbox SecurityPolicy | Strengere Defaults, isAlwaysAllowedInSandbox() | Projekte mit Sandbox | Strict-Mode auf 3.x testen |
Betrifft Sie das? Schnelltest in 30 Sekunden
Sofort prüfen wenn: Sie eigene Twig-Extensions mit getOperators() oder benutzerdefinierten Operatoren entwickeln. Die API entfällt in Twig 4.0.
Templates prüfen wenn: Sie loop.length, loop.revindex oder loop.revindex0 in Schleifen nutzen, die über Generator-Outputs oder nicht-zählbare Iteratoren iterieren.
Keine sofortige Aktion nötig wenn: Ihre Templates ausschließlich Arrays und Doctrine Collections iterieren. Das Twig-3.x-Verhalten bleibt vollständig kompatibel.
Twig-Extension mit eigenen Operatoren?
Die getOperators()-API entfällt in Twig 4.0. Ich helfe Ihnen einzuschätzen, welche Extensions angepasst werden müssen und was das bedeutet.
- Twig-Extensions seit Version 1.x
- Symfony-Template-Architektur aus der Praxis
⏱️ Antwort binnen 24 Stunden
Was steckt hinter dem for-Loop-Rebuild?
Die fundamentale Frage bei der alten for-Loop-Implementierung: Woher weiß Twig, ob der aktuelle Iterationsschritt der letzte ist? Bei Arrays ist das trivial, die Länge ist bekannt. Bei Generatoren und beliebigen Traversable-Objekten ist es unmöglich, ohne einen zusätzlichen Trick.
Potencier hat diesen Trick implementiert: Die neue Loop-Maschinerie liest einen Schritt voraus (Look-Ahead). Sie fetcht den nächsten Wert aus dem Iterator, bevor sie den aktuellen rendert. Wenn der Look-Ahead keinen Wert mehr liefert, weiß Twig: Der aktuelle Schritt ist der letzte. loop.last ist damit korrekt für jeden Iterator, nicht nur für Arrays.
{# Twig 4.0: loop.last funktioniert jetzt mit Generatoren #}
{% for item in generatorFunction() %}
{{ item.name }}
{% if not loop.last %}, {% endif %} {# Kein nachgestelltes Komma mehr #}
{% endfor %}
{# Das war das klassische Problem in Twig 3.x: #}
{# loop.last auf Generatoren lieferte immer false #}
{# Ergebnis: immer ein nachgestelltes Komma nach dem letzten Element #}Das erklärt auch, warum loop.length, loop.revindex und loop.revindex0 jetzt auf nicht-zählbaren Iteratoren einen klaren Fehler werfen. Diese Werte setzen eine bekannte Gesamtlänge voraus. Ein Generator hat keine Gesamtlänge, bevor er vollständig abgearbeitet ist. Twig 3.x hat hier stillschweigend leere Werte geliefert, ein bekannter Bug-Magnet für nachgestellte Kommas und fehlende Trennzeichen in Templatesn.
Was bringt die Rückkehr von for...if?
In Twig 3.0 wurde die for...if-Bedingung entfernt. Der Grund damals: Sie verhielt sich überraschend im Zusammenspiel mit loop.index und loop.length. Wenn man 10 Elemente hatte, aber nur 3 die Bedingung erfüllten, was war dann loop.index? Der Index im Original-Array oder der Index der gefilterten Elemente?
Twig 3.0 hatte sich für "entfernen statt dokumentieren" entschieden. Twig 4.0 kehrt zurück, mit klarer Semantik: loop.*-Variablen beziehen sich auf die gefilterte Sammlung.
{# Twig 4.0: for...if zurück #}
{% for user in users if user.active %}
{{ loop.index }}. {{ user.name }} {# Index der aktiven User, nicht aller User #}
{% else %}
Keine aktiven User gefunden.
{% endfor %}Was viele unterschätzen: Die else-Klausel funktioniert jetzt auch korrekt im Zusammenspiel mit for...if. In Twig 3.x war das ein häufiger Fehler: {% else %} zeigte den Fallback, wenn die ursprüngliche Sammlung leer war, nicht wenn alle Elemente herausgefiltert wurden.
loop.last zuverlässig für jeden Iterator. for...if kehrt zurück mit klarer Semantik. Keine Deprecations auf dem 3.x-Branch für Template-Autoren.
Was müssen Extension-Autoren jetzt tun?
Hier liegt der eigentliche Handlungsbedarf: Der Expression-Parser wurde neu geschrieben, basierend auf Vaughan Pratts "Top Down Operator Precedence" (einem der einflussreichsten Parser-Algorithmen der Informatik). Das Ergebnis ist ein saubererer, besser erweiterbarer Parser.
Der Breaking Change: Die bisherige getOperators()-Methode in AbstractExtension entfällt. Sie wird ersetzt durch getExpressionParsers() und die neue Methode getOperatorTokens().
// Twig 3.x: getOperators() für eigene Operatoren
class MyExtension extends AbstractExtension
{
public function getOperators(): array
{
return [
[/* Unary operators */],
[/* Binary operators */],
];
}
}
// Twig 4.0: neue API
class MyExtension extends AbstractExtension
{
public function getExpressionParsers(): array
{
// Gibt ExpressionParser-Objekte zurück
return [new MyCustomOperatorParser()];
}
public function getOperatorTokens(): array
{
// Registriert Tokens die als Operatoren erkannt werden
return ['my_operator'];
}
}Für Standard-Symfony-Projekte, die nur Core-Twig-Features nutzen, ist das kein Problem. Für Teams, die eigene Twig-Extensions mit benutzerdefinierten Operatoren gebaut haben, ist das ein Migration-Task. Die Komplexität hängt davon ab, wie viele eigene Operatoren in Verwendung sind.
Wie ich im Twig-3.27-Artikel beschrieben habe, hat der Strict Mode für die SecurityPolicy auf 3.x eine wichtige Vorab-Testfunktion: Wer ihn jetzt aktiviert, bekommt das Twig-4.0-Sandbox-Verhalten bereits heute und kann Probleme frühzeitig identifizieren.
Jetzt auf Twig 3.x vorbereiten: Aktivieren Sie den Strict Mode der SecurityPolicy auf Ihrem Twig-3.x-Setup, um das 4.0-Verhalten heute schon zu testen. Und: loop.length/revindex auf Generatoren in Staging provozieren, bevor 4.0 stable wird.
getOperators(): Migration auf getExpressionParsers() und getOperatorTokens() einplanen. Template-Autoren ohne eigene Extensions: keine Aktion nötig.
⚡ Twig-Extension-Audit vor 4.0?
Ich prüfe welche Ihrer Extensions die neue API benötigen und begleite die Migration auf Twig 4.0 sobald GA erscheint.
- Twig-Extensions und Custom-Operators aus der Praxis
- Symfony-Template-Stack seit Jahren im Einsatz
⏱️ Antwort binnen 24 Stunden
📞 Oder direkt anrufen: 04481 - 9099658
Was bedeutet das für bestehende Projekte?
Die gute Nachricht zuerst: Potenciers eigene Aussage ist eindeutig: "The for rework introduces no deprecations on the 3.x branch: a template that runs deprecation-free on Twig 3 renders identically on Twig 4.0, with the lone exception that reading loop.length, loop.revindex, or loop.revindex0 on a non-countable iterator now raises a clear error instead of producing empty output."
Das ist eine außerordentlich saubere Migration für Template-Autoren. Wenn Ihre Templates auf Twig 3.x ohne Deprecation-Warnings laufen, laufen sie auch auf Twig 4.0, mit einer einzigen Ausnahme.
Welche Templates müssen geprüft werden?
Twig kennt keine statische Analyse. Das heißt: Der einzige Weg, Loop-Probleme zu finden, ist ein Runtime-Test. Meine Empfehlung für die Vorbereitung:
Schritt 1: Alle Templates suchen, die loop.length, loop.revindex oder loop.revindex0 nutzen:
# Alle Templates nach loop.length/revindex suchen:
$ grep -r "loop\.length\|loop\.revindex" templates/
# In Symfony:
$ find templates/ -name "*.html.twig" -exec grep -l "loop\.length\|loop\.revindex" {} \;Schritt 2: Für jede gefundene Stelle prüfen: Wird über ein Array oder eine Doctrine Collection iteriert (zählbar) oder über einen Generator, einen lazy Iterator oder ein Traversable-Objekt (nicht-zählbar)?
Schritt 3: Strict Mode der SecurityPolicy auf Twig 3.x aktivieren (falls Sandbox im Einsatz) und Staging-Tests durchführen.
Als Symfony-Entwickler mit Fokus auf Template-Architektur sehe ich eine Regel, die sich bewährt hat: Generator-basierte Template-Daten sollten immer über Doctrine ArrayCollection oder einen explizit zählbaren Wrapper an Twig übergeben werden, wenn loop.*-Variablen genutzt werden. Twig 4.0 macht diese Empfehlung verbindlich.
Aus der Praxis: Was Template-Bugs wirklich kostet
Aus der Praxis
Was mir bei Code-Reviews und Einarbeitungen in Bestandssysteme häufig begegnet: Das nachgestellte Komma-Problem ist ein Klassiker. Eine Liste rendert korrekt in 99% der Fälle. Im 1%-Fall, wenn ein Service statt eines Arrays einen Generator zurückgibt, erscheint ein zusätzliches Komma nach dem letzten Element. Das ist schwer zu reproduzieren, weil es vom Datentyp der zurückgegebenen Sammlung abhängt. Twig 4.0 macht solche stillen Fehler zu expliziten Exceptions. Das ist in der Entwicklung lästiger, in Production deutlich sicherer.
Für Projekte, die nach Twig 4.0 GA migrieren wollen: Der Zeitplan ist noch nicht kommuniziert. Twig 4.0.0-alpha1 erschien am 17. Mai 2026. Bei Twig-Versionshistorie (3.0 erschien im November 2020) ist mit einem GA-Release nicht vor Ende 2026 zu rechnen. Das gibt ausreichend Zeit für eine strukturierte Vorbereitung.
Zusammenfassung
Loop-Rebuild: loop.last funktioniert jetzt mit jedem Iterator. Look-Ahead-Mechanismus. Keine Deprecations für Template-Autoren auf dem 3.x-Branch.
for...if zurück: Mit klarer Semantik (loop.* bezieht sich auf gefilterte Sammlung). else funktioniert korrekt mit gefilterten Ergebnissen.
Einzige Ausnahme: loop.length, loop.revindex, loop.revindex0 auf nicht-zählbaren Iteratoren werfen jetzt einen klaren Error.
Extension-Autoren: getOperators() entfällt. Migration auf getExpressionParsers() und getOperatorTokens() erforderlich.
Vorbereitung jetzt: Strict Mode auf 3.x aktivieren. Templates nach loop.length/revindex durchsuchen. Generator-basierte Daten auf zählbare Wrapper prüfen.
Twig-Templates und Extensions: Sie wissen, was zu prüfen ist.
Loop-Checks, Extension-Migration, Strict-Mode-Testing. Lassen Sie uns klären, was für Ihr Projekt konkret zu tun ist.
- Twig-Template-Architektur seit Version 1.x
- Custom Extensions und Operator-Migration
- Symfony-Template-Stack aus der Praxis