php 如何在 Twig 模板中的 for 循环中使用 break 或 continue?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21672796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I use break or continue within for loop in Twig template?
提问by Victor Bocharsky
I try to use a simple loop, in my real code this loop is more complex, and I need to breakthis iteration like:
我尝试使用一个简单的循环,在我的实际代码中,这个循环更复杂,我需要break这样的迭代:
{% for post in posts %}
{% if post.id == 10 %}
{# break #}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
How can I use behavior of breakor continueof PHP control structures in Twig?
我如何使用的行为,break或continue在枝杈PHP控制结构?
回答by Victor Bocharsky
This can be nearlydone by setting a new variable as a flag to breakiterating:
这几乎可以通过将新变量设置为break迭代标志来完成:
{% set break = false %}
{% for post in posts if not break %}
<h2>{{ post.heading }}</h2>
{% if post.id == 10 %}
{% set break = true %}
{% endif %}
{% endfor %}
An uglier, but working example for continue:
一个丑陋但有效的例子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 %}
But there is noperformance profit, only similar behaviour to the built-in
breakandcontinuestatements like in flat PHP.
但是没有性能收益,只有类似于flat PHP 中的内置
break和continue语句的行为。
回答by NHG
From docs TWIG docs:
来自文档 TWIG文档:
Unlike in PHP, it's not possible to break or continue in a loop.
与 PHP 不同的是,不可能在循环中中断或继续。
But still:
但仍然:
You can however filter the sequence during iteration which allows you to skip items.
但是,您可以在迭代期间过滤序列,从而可以跳过项目。
Example 1 (for huge lists you can filter posts using slice, slice(start, length)):
示例 1(对于大型列表,您可以使用slice,过滤帖子slice(start, length)):
{% for post in posts|slice(0,10) %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Example 2:
示例 2:
{% for post in posts if post.id < 10 %}
<h2>{{ post.heading }}</h2>
{% endfor %}
You can even use own TWIG filtersfor more complexed conditions, like:
您甚至可以将自己的TWIG 过滤器用于更复杂的条件,例如:
{% for post in posts|onlySuperPosts %}
<h2>{{ post.heading }}</h2>
{% endfor %}
回答by Jules Lamur
A way to be able to use {% break %}or {% continue %}is to write TokenParsers for them.
一种能够使用{% break %}或为它们{% continue %}编写TokenParsers 的方法。
I did it for the {% break %}token in the code below. You can, without much modifications, do the same thing for the {% continue %}.
我{% break %}在下面的代码中为令牌做了它。无需太多修改,您就可以对{% 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") ; } }
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 get out of loops like this:
然后你可以简单地使用{% break %}来摆脱这样的循环:
{% for post in posts %}
{% if post.id == 10 %}
{% break %}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
To go even further, you may write token parsers for {% continue X %}and {% break X %}(where X is an integer >= 1) to get out/continue multiple loops like in PHP.
更进一步,您可以为{% continue X %}and {% break X %}(其中 X 是一个整数 >= 1)编写标记解析器以退出/继续多个循环,就像在 PHP 中一样。
回答by Basit
From @NHG comment —?works perfectly
来自@NHG 评论——?完美运行
{% for post in posts|slice(0,10) %}
回答by paidforbychrist
I have found a good work-around for continue (love the break sample above). Here I do not want to list "agency". In PHP I'd "continue" but in twig, I came up with alternative:
我找到了一个很好的继续解决方法(喜欢上面的中断示例)。这里我不想列出“代理”。在 PHP 中,我会“继续”,但在 twig 中,我想出了替代方案:
{% for basename, perms in permsByBasenames %}
{% if basename == 'agency' %}
{# do nothing #}
{% else %}
<a class="scrollLink" onclick='scrollToSpot("#{{ basename }}")'>{{ basename }}</a>
{% endif %}
{% endfor %}
OR I simply skip it if it doesn't meet my criteria:
或者如果它不符合我的标准,我只是跳过它:
{% for tr in time_reports %}
{% if not tr.isApproved %}
.....
{% endif %}
{% endfor %}

