Подтвердить что ты не робот

Как остановить или освободиться от цикла 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 %}
4b9b3361

Ответ 1

Вы можете сделать что-то подобное, чтобы имитировать шаблон:

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

Вы также можете написать свой собственный, настраиваемый для цикла, я думаю.

Ответ 2

Я прочитал все ответы, и я согласен с ними, но не совсем прав, поэтому я решил написать тоже.

Прежде всего, поскольку @CristiC777 указал в своем сообщении, если вы достигнете случая, когда вам нужно сломать a, вы делаете что-то неправильно до этого момента. Вероятно, вы можете исправить это, просто поставив лимит на свои запросы или отключив данные из своих массивов. Это лучшее решение, потому что вы улучшите время отклика и сохраните память сервера.

Взгляды Twig должны быть глупыми. Если вы добавите в них кучу условий и переменных, вы сделаете их нечитабельными и неподъемными.

Если по какой-то причине вы не можете изменить предыдущий код, так как @Edgar Alloro указал, Twig позволяет устанавливать условия для a для (начиная с 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 %}

Ответ 3

Прежде всего,
подготовьте свои данные в контроллере и отправьте только, что вам нужно в twig!
, потому что веточка view strong > , и не рекомендуется играть с большими списками. Подумайте о том, что вы можете оказаться в ситуации, когда вы загружаете множество объектов или объектов, которые вы не используете.

поэтому, если вы все еще хотите, вам придется долгое время использовать решение Эдгара Аллоро с переменной, объявленной перед циклом. Или я знаю, что эта итерация LastIndex пытается установить это, когда вы хотите заблокировать цикл.

Удачи!;)

Ответ 4

согласно документации, невозможно разбить или продолжить в цикле. Тем не менее, вы можете фильтровать последовательность во время итерации, которая позволяет пропустить элементы. В следующем примере пропускаются все пользователи, которые неактивны:

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

Ответ 5

Создайте 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 %}, чтобы получить/продолжить несколько циклов, как в PHP.

Если кто-то хочет сделать это и поделиться им, не стесняйтесь редактировать мой ответ.

Ответ 6

{% set break = false %}

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