while loop last item for first array php symfony for-loop twig break

php - for - twig last item in loop



¿Cómo puedo utilizar break o continue for for loop en Twig template? (5)

De docs documentos TWIG:

A diferencia de PHP, no es posible romper o continuar en un bucle.

Pero aún:

Sin embargo, puede filtrar la secuencia durante la iteración, lo que le permite saltear elementos.

Ejemplo:

{% for post in posts if post.id < 10 %} <h2>{{ post.heading }}</h2> {% endfor %}

Incluso puede usar filtros TWIG propios para condiciones más complejas, como:

{% for post in posts|onlySuperPosts %} <h2>{{ post.heading }}</h2> {% endfor %}

Intento usar un bucle simple, en mi código real este ciclo es más complejo, y necesito break esta iteración como:

{% for post in posts %} {% if post.id == 10 %} {# break #} {% endif %} <h2>{{ post.heading }}</h2> {% endfor %}

¿Cómo puedo usar el comportamiento de break o continue las estructuras de control de PHP en Twig?


Del comentario de @NHG: funciona a la perfección

{% for post in posts|slice(0,10) %}


Esto puede casi hacerse al establecer una nueva variable como indicador para break iteración:

{% set break = false %} {% for post in posts if not break %} <h2>{{ post.heading }}</h2> {% if post.id == 10 %} {% set break = true %} {% endif %} {% endfor %}

Más feo, pero ejemplo de trabajo para 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 %}

Pero no hay beneficio de rendimiento, solo un comportamiento similar al de break incorporada y declaraciones continue como en PHP plano.


He encontrado una buena solución para continuar (me encanta la muestra de ruptura anterior). Aquí no quiero enumerar "agencia". En PHP, yo "continuaría" pero en twig, se me ocurrió una alternativa:

{% for basename, perms in permsByBasenames %} {% if basename == ''agency'' %} {# do nothing #} {% else %} <a class="scrollLink" onclick=''scrollToSpot("#{{ basename }}")''>{{ basename }}</a> {% endif %} {% endfor %}

O simplemente lo omito si no cumple mis criterios:

{% for tr in time_reports %} {% if not tr.isApproved %} ..... {% endif %} {% endfor %}


Una forma de poder usar {% break %} o {% continue %} es escribir TokenParser s para ellos.

Lo hice por el token {% break %} en el siguiente código. Puedes, sin muchas modificaciones, hacer lo mismo para {% continue %} .

  • 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") ; } }

Entonces simplemente puede usar {% break %} para salir de los bucles como este:

{% for post in posts %} {% if post.id == 10 %} {% break %} {% endif %} <h2>{{ post.heading }}</h2> {% endfor %}

Para ir más allá, puede escribir analizadores de tokens para {% continue X %} y {% break X %} (donde X es un entero> = 1) para salir / continuar múltiples bucles como en PHP .