Comment puis-je utiliser break ou continuer dans For loop dans le modèle Twig?
J'essaie d'utiliser une boucle simple, dans mon vrai code de cette boucle est plus complexe, et j'ai besoin de break
cette itération comme:
{% for post in posts %}
{% if post.id == 10 %}
{# break #}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Comment puis-je utiliser le comportement de break
ou continue
des structures de contrôle PHP dans Twig?
5 réponses
De Docs TWIG docs :
Contrairement à PHP, il n'est pas possible de casser ou de continuer en boucle.
Mais quand même:
Vous pouvez cependant filtrer la séquence pendant l'itération, ce qui vous permet de sauter des éléments.
Exemple:
{% for post in posts if post.id < 10 %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Vous pouvez même utiliser vos propres filtres TWIG pour des conditions plus complexes, comme:
{% for post in posts|onlySuperPosts %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Cela peut être presque en définissant une nouvelle variable comme indicateur sur break
itération:
{% set break = false %}
{% for post in posts if not break %}
<h2>{{ post.heading }}</h2>
{% if post.id == 10 %}
{% set break = true %}
{% endif %}
{% endfor %}
Plus laid, mais exemple de travail pour 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 %}
Mais il n'y a Pas de profit de performance, seulement un comportement similaire aux instructions
break
etcontinue
intégrées comme en PHP plat.
De @ NHG comment-fonctionne parfaitement
{% for post in posts|slice(0,10) %}
, pour être en mesure d'utiliser {% break %}
ou {% continue %}
est d'écrire TokenParser
s pour eux.
Je l'ai fait pour le jeton {% break %}
dans le code ci-dessous. Vous pouvez, sans trop de modifications, faire la même chose pour le {% continue %}
.
-
AppBundle \ Brindille \ AppExtension.php :
namespace AppBundle\Twig; class AppExtension extends \Twig_Extension { function getTokenParsers() { return array( new BreakToken(), ); } public function getName() { return 'app_extension'; } }
-
AppBundle \ Brindille \ 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") ; } }
, Alors vous pouvez simplement utiliser {% break %}
pour sortir des boucles comme ceci:
{% for post in posts %}
{% if post.id == 10 %}
{% break %}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Pour aller encore plus loin, vous pouvez écrire des analyseurs de jetons pour {% continue X %}
et {% break X %}
(où X est un entier >= 1) pour sortir/continuer plusieurs boucles comme en PHP.
J'ai trouvé un bon travail pour continuer (j'aime l'échantillon de pause ci-dessus). Ici, Je ne veux pas énumérer "agence". En PHP, je "continuerais" mais dans twig, je suis venu avec une alternative:
{% for basename, perms in permsByBasenames %}
{% if basename == 'agency' %}
{# do nothing #}
{% else %}
<a class="scrollLink" onclick='scrollToSpot("#{{ basename }}")'>{{ basename }}</a>
{% endif %}
{% endfor %}
Ou je l'ignore simplement s'il ne répond pas à mes critères:
{% for tr in time_reports %}
{% if not tr.isApproved %}
.....
{% endif %}
{% endfor %}