Ich versuche, eine einfache Schleife zu verwenden. In meinem realen Code ist diese Schleife komplexer und ich muss break
diese Iteration wie folgt ausführen:
{% for post in posts %}
{% if post.id == 10 %}
{# break #}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Wie kann ich das Verhalten von break
oder continue
von PHP Kontrollstrukturen in Twig verwenden?
Dies kann fast erreicht werden, indem eine neue Variable als Flag auf break
gesetzt wird.
{% set break = false %}
{% for post in posts if not break %}
<h2>{{ post.heading }}</h2>
{% if post.id == 10 %}
{% set break = true %}
{% endif %}
{% endfor %}
Hässlicher, aber Arbeitsbeispiel für continue
:
{% set continue = false %}
{% for post in posts %}
{% if post.id == 10 %}
{% set continue = true %}
{% endif %}
{% if not continue %}
<h2>{{ post.heading }}</h2>
{% endif %}
{% if continue %}
{% set continue = false %}
{% endif %}
{% endfor %}
Aber es gibt no Performance Profit, nur ähnliches Verhalten wie bei den eingebauten Anweisungen
break
undcontinue
wie bei flachem PHP.
Von docs TWIG docs :
Anders als in PHP ist es nicht möglich, eine Schleife zu unterbrechen oder fortzusetzen.
Aber dennoch:
Sie können die Reihenfolge jedoch während der Iteration filtern, sodass Sie Elemente überspringen können.
Beispiel 1 (für große Listen können Sie Posts mit Slice , slice(start, length)
filtern):
{% for post in posts|slice(0,10) %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Beispiel 2:
{% for post in posts if post.id < 10 %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Sie können auch eigene TWIG-Filter für komplexere Bedingungen verwenden, wie z.
{% for post in posts|onlySuperPosts %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Von @NHG Kommentar - funktioniert einwandfrei
{% for post in posts|slice(0,10) %}
Eine Möglichkeit, {% break %}
Oder {% continue %}
Zu verwenden, besteht darin, TokenParser
s für sie zu schreiben.
Ich habe es für den Token {% break %}
Im folgenden Code getan. Sie können ohne große Modifikationen dasselbe für den {% continue %}
Tun.
AppBundle\Twig\AppExtension.php :
namespace AppBundle\Twig;
class AppExtension extends \Twig_Extension
{
function getTokenParsers() {
return array(
new BreakToken(),
);
}
public function getName()
{
return 'app_extension';
}
}
AppBundle\Twig\BreakToken.php :
namespace AppBundle\Twig;
class BreakToken extends \Twig_TokenParser
{
public function parse(\Twig_Token $token)
{
$stream = $this->parser->getStream();
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
// Trick to check if we are currently in a loop.
$currentForLoop = 0;
for ($i = 1; true; $i++) {
try {
// if we look before the beginning of the stream
// the stream will throw a \Twig_Error_Syntax
$token = $stream->look(-$i);
} catch (\Twig_Error_Syntax $e) {
break;
}
if ($token->test(\Twig_Token::NAME_TYPE, 'for')) {
$currentForLoop++;
} else if ($token->test(\Twig_Token::NAME_TYPE, 'endfor')) {
$currentForLoop--;
}
}
if ($currentForLoop < 1) {
throw new \Twig_Error_Syntax(
'Break tag is only allowed in \'for\' loops.',
$stream->getCurrent()->getLine(),
$stream->getSourceContext()->getName()
);
}
return new BreakNode();
}
public function getTag()
{
return 'break';
}
}
AppBundle\Twig\BreakNode.php :
namespace AppBundle\Twig;
class BreakNode extends \Twig_Node
{
public function compile(\Twig_Compiler $compiler)
{
$compiler
->write("break;\n")
;
}
}
Dann können Sie einfach {% break %}
Verwenden, um Schleifen wie folgt zu verlassen:
{% for post in posts %}
{% if post.id == 10 %}
{% break %}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Um noch weiter zu gehen, können Sie Token-Parser für {% continue X %}
Und {% break X %}
(Wobei X eine Ganzzahl> = 1 ist) schreiben, um mehrere Schleifen wie in PHP auszulösen/fortzusetzen =.
Ich habe eine gute Lösung gefunden, um fortzufahren (ich liebe das Pausenmuster oben). Hier möchte ich nicht "Agentur" auflisten. In PHP Ich würde "weitermachen", aber im Zweig habe ich mir eine Alternative ausgedacht:
{% for basename, perms in permsByBasenames %}
{% if basename == 'agency' %}
{# do nothing #}
{% else %}
<a class="scrollLink" onclick='scrollToSpot("#{{ basename }}")'>{{ basename }}</a>
{% endif %}
{% endfor %}
ODER ich überspringe es einfach, wenn es nicht meinen Kriterien entspricht:
{% for tr in time_reports %}
{% if not tr.isApproved %}
.....
{% endif %}
{% endfor %}