The way to use {% break %} or {% continue %} is to write TokenParser for them.
I did this for the token {% break %} in the code below. You can do the same for {% continue %} without much change.
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") ; } }
Then you can simply use {% break %} to exit the loops, for example:
{% for post in posts %} {% if post.id == 10 %} {% break %} {% endif %} <h2>{{ post.heading }}</h2> {% endfor %}
To go even further, you can write parsers for {% continue X %} and {% break X %} (where X is an integer> = 1) in exit / continue several cycles, as in PHP .
Jules Lamur Dec 03 '16 at 15:25 2016-12-03 15:25
source share