Я пытаюсь использовать простой цикл, в моем реальном коде этот цикл более сложный, и мне нужно break
эту итерацию:
{% for post in posts %}
{% if post.id == 10 %}
{# break #}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Как я могу использовать поведение break
или continue
структур управления PHP в Twig?
Это может быть почти, если установить новую переменную в качестве флага для break
итерации:
{% set break = false %}
{% for post in posts if not break %}
<h2>{{ post.heading }}</h2>
{% if post.id == 10 %}
{% set break = true %}
{% endif %}
{% endfor %}
Более уродливый, но пример работы для continue
:
{% set continue = false %}
{% for post in posts %}
{% if post.id == 10 %}
{% set continue = true %}
{% endif %}
{% if not continue %}
<h2>{{ post.heading }}</h2>
{% endif %}
{% if continue %}
{% set continue = false %}
{% endif %}
{% endfor %}
Но производительность производительности нет, только аналогичное поведение со встроенными операторами
break
иcontinue
, как в плоском PHP.
Из документов TWIG docs:
В отличие от PHP, невозможно прерывать или продолжать в цикле.
Но все же:
Однако вы можете фильтровать последовательность во время итерации, что позволяет пропустить элементы.
Пример:
{% for post in posts if post.id < 10 %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Вы можете использовать собственные TWIG фильтры для более сложных условий, например:
{% for post in posts|onlySuperPosts %}
<h2>{{ post.heading }}</h2>
{% endfor %}
{% for post in posts|slice(0,10) %}
Unlike in PHP, it's not possible to break or continue in a loop.
когда читаешь документы. Но я думаю, что break
и continue
это хорошие функции, которые нужно добавить
Способ использования {% break %}
или {% continue %}
заключается в записи TokenParser
для них.
Я сделал это для токена {% break %}
в коде ниже. Вы можете без особых изменений сделать то же самое для {% continue %}
.
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;
for ($i = 1; true; $i++) {
try {
// if we look before the beginning of the stream
// the stream will throw a \Twig_Error_Syntax
$token = $stream->look(-$i);
} catch (\Twig_Error_Syntax $e) {
break;
}
if ($token->test(\Twig_Token::NAME_TYPE, 'for')) {
$currentForLoop++;
} else if ($token->test(\Twig_Token::NAME_TYPE, 'endfor')) {
$currentForLoop--;
}
}
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 %}
, чтобы выйти из циклов, например:
{% for post in posts %}
{% if post.id == 10 %}
{% break %}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Чтобы идти еще дальше, вы можете писать парсеры для {% continue X %}
и {% break X %}
(где X - целое число >= 1) в выйти/продолжить несколько циклов, как в PHP.
Я нашел хорошую работу для продолжения (см. выше пример опроса). Здесь я не хочу перечислить "агентство". В PHP я бы "продолжал", но в twig, я придумал альтернативу:
{% for basename, perms in permsByBasenames %}
{% if basename == 'agency' %}
{# do nothing #}
{% else %}
<a class="scrollLink" onclick='scrollToSpot("#{{ basename }}")'>{{ basename }}</a>
{% endif %}
{% endfor %}
ИЛИ Я просто пропустил его, если он не соответствует моим критериям:
{% for tr in time_reports %}
{% if not tr.isApproved %}
.....
{% endif %}
{% endfor %}
Из комментария @NHG - отлично работает
{% for post in posts|slice(0,10) %}
first
фильтр веток : twig.sensiolabs.org/doc/filters/first.html