如何停止或摆脱Twig循环?

时间:2015-02-24 13:44:39

标签: php symfony loops twig

在PHP中,您可以从循环中断或继续下一次迭代。我想知道你是否在Symfony的Twig中拥有相同的功能。

例如,在PHP中我可以这样做:

foreach ($array as $key => $value) {
    if ($value == 'something') {
        continue;
    } elseif ($value == 'somethingElse') {
        break;
    }
    echo $value;
}

Twig中有类似的东西吗?例如:

{% for value in array %}
    {% if value == 'something' %}
    {% continue %}
    {% endif %}
    {% if value == 'somethingElse' %}
    {% break %}
    {% endif %}
    {{ value }}
{% endfor %}

6 个答案:

答案 0 :(得分:14)

你可以做这样的事情,以模拟模式:

{% set breakLoop = false %}

{% for value in array if breakLoop == false %}
    {% if value == 'somethingElse' %}
        {% breakLoop = true %}
    {% endif %}

    {% if value != 'something' and breakLoop == false %}


        {{ value }}
    {% endif %}
{% endfor %}

只需将代码包装在条件内即可继续。

用于破坏使用从for循环外部可见的变量。

我猜你也可以编写自己的自定义for循环。

答案 1 :(得分:9)

我已经阅读了所有的答案,我同意他们的观点,但并不完全正确,所以我决定也写下我的答案。

首先,正如@CristiC777在他的消息中指出的那样,如果你达到需要打破for的情况,你在此之前做错了什么。您可以解决此问题,只是限制查询或从阵列中取消设置数据。这是一个更好的解决方案,因为您将缩短响应时间并节省服务器内存。

  

Twig视图需要愚蠢。如果你将一堆条件和变量放入其中,你只能使它们不可读且不可维护。

如果出于某种原因,你不能改变以前的代码,正如@Edgar Alloro指出的那样,Twig允许你put conditions on a for(从1.2开始)。您的示例将更改为以下内容:

{% set keepFor = true %}

{% for value in array if keepFor %}

    {% if value != 'valueExpected' %}

        {% keepFor = false %}

    {% endif %}

    {{ value }}

{% endfor %}

您也可以自己实施,特别是如果您没有Twig 1.2。如果你有Twig 1.2或者以上我不推荐这个,因为for会迭代整个数组,你会花更多的内存

{% set keepFor = true %}

{% for value in array %}

    {% if keepFor %}

        {% if value != 'valueExpected' %}

            {% keepFor = false %}

        {% endif %}

        {{ value }}

    {% endif %}

{% endfor %}

答案 2 :(得分:8)

首先!在控制器中准备您的数据,然后在树枝上发送 您需要的内容!
因为树枝视图,不建议使用大型列表。想一想,当您加载查看许多您不会使用的对象或实体时,您会发现自己处于这种情况。

所以,如果你仍然希望有一个艰难的生活,请使用Edgar Alloro解决方案,并在循环之前声明一个变量。或者我知道这个迭代有LastIndex尝试设置当你想要制动循环..

玩得开心! ;)

答案 3 :(得分:6)

根据文档,不可能在循环中中断或继续。但是,您可以在迭代期间过滤序列,以便跳过项目。以下示例将跳过所有未激活的用户:

<ul>
{% for user in users if user.active %}
    <li>{{ user.username }}</li>
{% endfor %}
</ul>

答案 4 :(得分:5)

使用以下类创建TwigExtension

  • 的appbundle \嫩枝\ AppExtension.php:

    namespace AppBundle\Twig;
    
    class AppExtension extends \Twig_Extension
    {
        function getTokenParsers() {
            return array(
                new BreakToken(),
            );
        }
    
        public function getName()
        {
            return 'app_extension';
        }
    }
    
  • 的appbundle \嫩枝\ 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;
            try { // This "try" is because look() will throws a PHP exception if $this->current - $i is negative (where $this is $stream).
                for ($i = 1; true; $i++) {
                    $token = $stream->look(-$i);
                    if ($token->test(\Twig_Token::NAME_TYPE, 'for')) {
                        $currentForLoop++;
                    } else if ($token->test(\Twig_Token::NAME_TYPE, 'endfor')) {
                        $currentForLoop--;
                    }
                }
            } catch (\Exception $e) {
            }
    
            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 \嫩枝\ BreakNode.php:

    namespace AppBundle\Twig;
    
    class BreakNode extends \Twig_Node
    {
        public function compile(\Twig_Compiler $compiler)
        {
            $compiler
                ->write("break;\n")
            ;
        }
    }
    

然后你可以简单地使用{% break %}来摆脱这样的循环:

{% set var = ['foo', 'bar'] %}
{% for v in var %}
    {{ v }}
    {% break %}
{% endfor %}

我没有足够的时间对其进行编码,但您可以用同样的方式编写continue块。

为了更进一步,您可以处理{% continue X %}{% break X %}以获取/继续多个循环,就像在PHP中一样。

如果有人想要这样做并分享,请随时编辑我的答案。

答案 5 :(得分:1)

{% set break = false %}

{% for value in array  if not break  %}
    {% if value == 'something' %}
    {% continue %}
    {% endif %}
    {% if value == 'somethingElse' %}
    {% set break = true %}
    {% endif %}
    {{ value }}
{% endfor %}