Vic*_*sky 85 php for-loop break symfony twig
我尝试使用一个简单的循环,在我的实际代码中这个循环更复杂,我需要break这样的迭代,如:
{% for post in posts %}
{% if post.id == 10 %}
{# break #}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
我如何使用的行为,break或continue在枝杈PHP控制结构?
NHG*_*NHG 112
来自docs TWIG 文档:
与PHP不同,它不可能在循环中中断或继续.
但仍然:
但是,您可以在迭代期间过滤序列,以便跳过项目.
例1(为巨大的列表,你可以使用过滤帖片,slice(start, length)):
{% for post in posts|slice(0,10) %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
例2:
{% for post in posts if post.id < 10 %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
您甚至可以使用自己的TWIG过滤器来处理更复杂的情况,例如:
{% for post in posts|onlySuperPosts %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
Vic*_*sky 108
这可以将近通过设置新的变量作为标志进行break迭代:
{% set break = false %}
{% for post in posts if not break %}
<h2>{{ post.heading }}</h2>
{% if post.id == 10 %}
{% set break = true %}
{% endif %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
更丑陋,但工作示例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 %}
Run Code Online (Sandbox Code Playgroud)
但是没有性能利润,只有与内置
break和continue类似扁平PHP的语句类似的行为.
一种能够使用{% break %}或{% continue %}正在TokenParser为它们编写s的方法.
我{% 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';
}
}
Run Code Online (Sandbox Code Playgroud)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';
}
}
Run Code Online (Sandbox Code Playgroud)AppBundle\Twig\BreakNode.php:
namespace AppBundle\Twig;
class BreakNode extends \Twig_Node
{
public function compile(\Twig_Compiler $compiler)
{
$compiler
->write("break;\n")
;
}
}
Run Code Online (Sandbox Code Playgroud)然后你可以简单地{% break %}用来摆脱这样的循环:
{% for post in posts %}
{% if post.id == 10 %}
{% break %}
{% endif %}
<h2>{{ post.heading }}</h2>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
为了更进一步,您可以为{% continue X %}和编写令牌解析器{% break X %}(其中X是一个整数> = 1)来获取/继续多个循环,就像在PHP中一样.
我已经找到了一个很好的继续工作(喜欢上面的休息样本).在这里,我不想列出"代理".在PHP中我会"继续",但在树枝上,我提出了替代方案:
{% for basename, perms in permsByBasenames %}
{% if basename == 'agency' %}
{# do nothing #}
{% else %}
<a class="scrollLink" onclick='scrollToSpot("#{{ basename }}")'>{{ basename }}</a>
{% endif %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
或者我只是跳过它,如果它不符合我的标准:
{% for tr in time_reports %}
{% if not tr.isApproved %}
.....
{% endif %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)