如何停止或摆脱 Twig 循环?

How to stop or break free from a Twig loop?

在 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 %}

您可以这样做,以模拟模式:

{% 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 循环。

首先 !
controller 中准备好你的数据,然后 just 在 twig 中发送你需要的数据!
因为 twig 是 view,不建议玩大列表。想一想当您在视图中加载很多您不使用的对象或实体时,您会发现自己处于这种情况。.

因此,如果您仍然想过着艰难的生活,请使用 Edgar Alloro 解决方案,并在循环之前声明一个变量。或者我知道这个迭代有 LastIndex 尝试在你想停止循环时设置它..

玩得开心! ;)

根据文档,无法中断或继续循环。但是,您可以在迭代期间过滤序列,从而允许您跳过项目。以下示例跳过所有不活动的用户:

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

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

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

Twig views need to be silly. If you put a bunch of conditions and variables into them, you will only make them unreadable and unmaintenable.

如果由于某种原因,您无法更改以前的代码,正如@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 %}

使用这些 类:

创建 TwigExtension
  • 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;
            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\Twig\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 %} 以获得 out/continue 多个循环,如 PHP.

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

{% set break = false %}

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