我尝试使用一个简单的循环,在我的实际代码中,这个循环更复杂,我需要break
这个迭代就像:
{% for post in posts %}
{% if post.id == 10 %}
{# break #}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
如何在Twig中使用break
或continue
PHP控件结构的行为?
答案 0 :(得分:104)
来自文档TWIG docs:
与PHP不同,它不可能在循环中中断或继续。
但仍然:
但是,您可以在迭代期间过滤序列,以便跳过项目。
示例1(对于大型列表,您可以使用slice,slice(start, length)
来过滤帖子):
{% for post in posts|slice(0,10) %}
<h2>{{ post.heading }}</h2>
{% endfor %}
示例2:
{% for post in posts if post.id < 10 %}
<h2>{{ post.heading }}</h2>
{% endfor %}
您甚至可以将自己的TWIG filters用于更复杂的条件,例如:
{% for post in posts|onlySuperPosts %}
<h2>{{ post.heading }}</h2>
{% endfor %}
答案 1 :(得分:95)
通过将新变量设置为break
迭代的标志,可以接近:
{% set break = false %}
{% for post in posts if not break %}
<h2>{{ post.heading }}</h2>
{% if post.id == 10 %}
{% set break = true %}
{% endif %}
{% endfor %}
更难看,但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 %}
但是没有性能利润,只有与内置
break
和continue
语句类似的行为,例如在平面PHP中。
答案 2 :(得分:9)
来自@NHG评论 - 效果很好
{% for post in posts|slice(0,10) %}
答案 3 :(得分:7)
能够使用{% continue %}
或TokenParser
的方法是为他们写{% break %}
。
我是为下面代码中的{% continue %}
令牌做的。您可以在不做任何修改的情况下为namespace AppBundle\Twig;
class AppExtension extends \Twig_Extension
{
function getTokenParsers() {
return array(
new BreakToken(),
);
}
public function getName()
{
return 'app_extension';
}
}
执行相同的操作。
<强>的appbundle \枝条\ AppExtension.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 \枝条\ BreakToken.php 强>:
namespace AppBundle\Twig;
class BreakNode extends \Twig_Node
{
public function compile(\Twig_Compiler $compiler)
{
$compiler
->write("break;\n")
;
}
}
<强>的appbundle \枝条\ BreakNode.php 强>:
{% break %}
然后你可以简单地使用{% for post in posts %}
{% if post.id == 10 %}
{% break %}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
来摆脱这样的循环:
{% continue X %}
为了更进一步,您可以将{% break X %}
和Random
(其中X是一个整数&gt; = 1)的令牌解析器编写为get out/continue multiple loops like in PHP。
答案 4 :(得分:6)
我已经找到了一个很好的继续工作(喜欢上面的休息样本)。 在这里,我不想列出&#34; agency&#34;。在PHP中我会继续&#34;但是在树枝上,我提出了替代方案:
{% for basename, perms in permsByBasenames %}
{% if basename == 'agency' %}
{# do nothing #}
{% else %}
<a class="scrollLink" onclick='scrollToSpot("#{{ basename }}")'>{{ basename }}</a>
{% endif %}
{% endfor %}
或者我只是跳过它,如果它不符合我的标准:
{% for tr in time_reports %}
{% if not tr.isApproved %}
.....
{% endif %}
{% endfor %}
答案 5 :(得分:0)
就这样尝试
{% for tr in time_reports %} {% if conditions %} ..... {% endif %} {% endfor %}