简体   繁体   English

如何停止或摆脱Twig循环?

[英]How to stop or break free from a Twig loop?

In PHP you've got the possibility to break from a loop or continue to the next iteration. 在PHP中,您可以中断循环或继续进行下一个迭代。 I was wondering if you've got the same functionality in Symfony's Twig. 我想知道您在Symfony的Twig中是否具有相同的功能。

For example, in PHP I am able to do: 例如,在PHP中,我可以执行以下操作:

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

Is there something similiar in Twig? 树枝上有什么类似的东西吗? For example something like: 例如:

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

You could do something like this, in order to simulate the pattern: 您可以执行以下操作以模拟模式:

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

Just wrap the code inside the condition to not continue. 只需将代码包装在条件中即可,不再继续。

For breaking use a variable visible from outside the for loop. 若要中断,请使用for循环外部可见的变量。

You could also write your own, custom for loop, I guess. 我想,您也可以编写自己的自定义for循环。

I've read all the answers and I agree with them but aren't totally right, so I decided to write mine too. 我已经阅读了所有答案,但我并不同意,所以我决定也写我的答案。

First of all, as @CristiC777 pointed in his message, if you reach the case where you need to break a for, you are doing something wrong before this point . 首先,正如@ CristiC777在他的消息中指出的那样,如果您遇到需要破译for的情况, 则在此之前您做错了什么 You probably can fix this just putting a limit on your queries or unsetting data from your arrays. 您可能仅通过限制查询或从数组中取消设置数据就可以解决此问题。 This is a better solution because you will improve the response time and save server memory. 这是一个更好的解决方案,因为您将缩短响应时间并节省服务器内存。

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. 如果将一堆条件和变量放入其中,则只会使它们变得不可读且无法维护。

If, for some reason, you cannot change the previous code, as @Edgar Alloro pointed, Twig allows you to put conditions on a for (since 1.2). 如果由于某种原因您不能更改前面的代码(如@Edgar Alloro指出的那样),则Twig允许您将条件放在for上 (从1.2开始)。 Your example will change to something like this: 您的示例将变为以下内容:

{% set keepFor = true %}

{% for value in array if keepFor %}

    {% if value != 'valueExpected' %}

        {% keepFor = false %}

    {% endif %}

    {{ value }}

{% endfor %}

You can also do your own implementation, specially if you don't have Twig 1.2. 您还可以执行自己的实现,特别是如果您没有Twig 1.2。 If you have Twig 1.2 or above I do not recommend this because the for will iterate the entire array and you will spend more memory : 如果您拥有Twig 1.2或更高版本, 我不建议您这样做,因为for会迭代整个数组,并且您将花费更多的内存

{% set keepFor = true %}

{% for value in array %}

    {% if keepFor %}

        {% if value != 'valueExpected' %}

            {% keepFor = false %}

        {% endif %}

        {{ value }}

    {% endif %}

{% endfor %}

First of all ! 首先 !
prepare your data in controller and send just what you need in twig ! 控制器准备数据, 只是您在树枝需要的东西送!
because twig is view , and is not recommend to play with big lists. 因为树枝是view ,不建议使用大列表。 Think about you can find yourself in the situation when you load in view a lot of objects or entities that you don't use .. 想一想,当您在视图中加载许多不使用的对象或实体时会发现自己处在这种情况下。

so if you still want do have a hard life use Edgar Alloro solution with a variable declared before loop. 因此,如果您仍然想过一段艰难的生活,请使用Edgar Alloro解决方案,并在循环之前声明一个变量。 Or I know this iteration has LastIndex try to set that when you want to brake the loop.. 或者我知道此迭代具有LastIndex可以在您希望制动循环时尝试设置该值。

Have fun ! 玩得开心 ! ;) ;)

according to documentation, it's not possible to break or continue in a loop. 根据文档,不可能中断或继续循环。 You can however filter the sequence during iteration which allows you to skip items. 但是,您可以在迭代过程中过滤序列,从而可以跳过项目。 The following example skips all the users which are not active: 下面的示例跳过所有不活动的用户:

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

Create a TwigExtension using these classes: 使用以下类创建一个TwigExtension

  • AppBundle\\Twig\\AppExtension.php: 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: 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: 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 %}退出循环,如下所示:

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

I don't have enough time to code it, but you could write the continue block the same way. 我没有足够的时间编写代码,但是您可以用相同的方式编写continue块。

To go even further, you may handle {% continue X %} and {% break X %} to get out/continue multiple loops like in PHP. 要走得更远,您可以处理{% continue X %}{% break X %}来退出/继续多个循环,就像在PHP中一样。

If someone wants to do it and share it, feel free to edit my answer. 如果有人要分享它,请随时编辑我的答案。

{% set break = false %}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM