如何停止或摆脱 Twig 循环?
How to stop or break free from a Twig loop?
在 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 %}
您可以这样做,以模拟模式:
{% 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 循环外部可见的变量。
我想您也可以编写自己的自定义 for 循环。
首先 !
在 controller 中准备好你的数据,然后 just 在 twig 中发送你需要的数据!
因为 twig 是 view,不建议玩大列表。想一想当您在视图中加载很多您不使用的对象或实体时,您会发现自己处于这种情况。.
因此,如果您仍然想过着艰难的生活,请使用 Edgar Alloro 解决方案,并在循环之前声明一个变量。或者我知道这个迭代有 LastIndex 尝试在你想停止循环时设置它..
玩得开心! ;)
根据文档,无法中断或继续循环。但是,您可以在迭代期间过滤序列,从而允许您跳过项目。以下示例跳过所有不活动的用户:
<ul>
{% for user in users if user.active %}
<li>{{ user.username }}</li>
{% endfor %}
</ul>
我已经阅读了所有的答案,我同意他们的看法,但并不完全正确,所以我决定也写下我的答案。
首先,正如@CristiC777 在他的消息中指出的那样,如果您遇到需要中断 for 的情况,您在此之前做错了什么。您可能可以通过限制查询或取消设置数组中的数据来解决此问题。这是一个更好的解决方案,因为您将缩短响应时间并节省服务器内存。
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.
如果由于某种原因,您无法更改以前的代码,正如@Edgar Alloro 指出的那样,Twig 允许您put conditions on a for(自 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 %}
使用这些 类:
创建 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 %}
以获得 out/continue 多个循环,如 PHP.
如果有人想做并分享,请随时编辑我的答案。
{% set break = false %}
{% for value in array if not break %}
{% if value == 'something' %}
{% continue %}
{% endif %}
{% if value == 'somethingElse' %}
{% set break = true %}
{% endif %}
{{ value }}
{% endfor %}
在 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 %}
您可以这样做,以模拟模式:
{% 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 循环外部可见的变量。
我想您也可以编写自己的自定义 for 循环。
首先 !
在 controller 中准备好你的数据,然后 just 在 twig 中发送你需要的数据!
因为 twig 是 view,不建议玩大列表。想一想当您在视图中加载很多您不使用的对象或实体时,您会发现自己处于这种情况。.
因此,如果您仍然想过着艰难的生活,请使用 Edgar Alloro 解决方案,并在循环之前声明一个变量。或者我知道这个迭代有 LastIndex 尝试在你想停止循环时设置它..
玩得开心! ;)
根据文档,无法中断或继续循环。但是,您可以在迭代期间过滤序列,从而允许您跳过项目。以下示例跳过所有不活动的用户:
<ul>
{% for user in users if user.active %}
<li>{{ user.username }}</li>
{% endfor %}
</ul>
我已经阅读了所有的答案,我同意他们的看法,但并不完全正确,所以我决定也写下我的答案。
首先,正如@CristiC777 在他的消息中指出的那样,如果您遇到需要中断 for 的情况,您在此之前做错了什么。您可能可以通过限制查询或取消设置数组中的数据来解决此问题。这是一个更好的解决方案,因为您将缩短响应时间并节省服务器内存。
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.
如果由于某种原因,您无法更改以前的代码,正如@Edgar Alloro 指出的那样,Twig 允许您put conditions on a for(自 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 %}
使用这些 类:
创建 TwigExtensionAppBundle\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 %}
以获得 out/continue 多个循环,如 PHP.
如果有人想做并分享,请随时编辑我的答案。
{% set break = false %}
{% for value in array if not break %}
{% if value == 'something' %}
{% continue %}
{% endif %}
{% if value == 'somethingElse' %}
{% set break = true %}
{% endif %}
{{ value }}
{% endfor %}