如何在Twig模板中使用break或continue for for循环?

时间:2014-02-10 09:04:31

标签: php symfony for-loop twig break

我尝试使用一个简单的循环,在我的实际代码中,这个循环更复杂,我需要break这个迭代就像:

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

如何在Twig中使用breakcontinue PHP控件结构的行为?

6 个答案:

答案 0 :(得分:104)

来自文档TWIG docs

  

与PHP不同,它不可能在循环中中断或继续。

但仍然:

  

但是,您可以在迭代期间过滤序列,以便跳过项目。

示例1(对于大型列表,您可以使用sliceslice(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 %}
  

但是没有性能利润,只有与内置breakcontinue语句类似的行为,例如在平面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 %}