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