如何停止或摆脱 Twig 循环?

Posted

技术标签:

【中文标题】如何停止或摆脱 Twig 循环?【英文标题】:How to stop or break free from a Twig loop? 【发布时间】:2015-04-26 04:08:06 【问题描述】:

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 %

【问题讨论】:

来自docs - “与 PHP 不同,它不可能在循环中中断或继续。但是,您可以在迭代期间过滤序列,从而允许您跳过项目。以下示例跳过所有不活跃的用户:" 是的 - 但您可以通过过滤器发挥创意来模拟休息时间。 How can I use break or continue within for in twig template?的可能重复 我为此使用 Angular.JS!看这里如何:http://***.com/questions/33853419/search-filter-angular-js-inside-twig-loop 我想给 CristiC777 的回答更多点赞。 Twig 是一种简单的模板语言,它是关于演示的。如果你不能在 Twig 中做某事,你可能有一些需要重写的时髦逻辑。如果您绝对必须“处理”数据,使用嵌入式控制器 (symfony.com/doc/current/templating/embedding_controllers.html) 会解决您的问题吗? IE。您不必担心页面上的逻辑,而是在控制器环境中按预期获取/解析数据集? 【参考方案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 循环外部可见的变量。

我猜你也可以编写自己的自定义 for 循环。

【讨论】:

这是正确答案,无需添加新的语言结构。【参考方案2】:

我已经阅读了所有的答案,我同意他们,但并不完全正确,所以我决定也写我的。

首先,正如@CristiC777 在他的消息中指出的那样,如果您遇到需要中断 for 的情况,在此之前您做错了什么。您可能可以解决此问题,只需限制您的查询或取消设置数组中的数据。这是一个更好的解决方案,因为您将缩短响应时间并节省服务器内存。

Twig 视图要傻。如果你把一堆条件和变量放进去,你只会让它们不可读和不可维护。

如果由于某种原因您无法更改之前的代码,正如@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 %

【讨论】:

我希望没有人使用 Twig 1.2,1.20 中有重大的安全修复。 如果您知道 Symfony 2.0 甚至 Symfony 1 中还有多少项目,您会感到惊讶。*【参考方案3】:

首先!在controller中准备好你的数据并发送just你在twig中需要的东西!因为twig是view strong>,不建议玩大列表。想想当你在视图中加载很多你不使用的对象或实体时,你会发现自己处于这种情况..

因此,如果您仍然想过上艰难的生活,请使用 Edgar Alloro 解决方案,并在循环之前声明一个变量。或者我知道这个迭代有 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 %

【讨论】:

以上是关于如何停止或摆脱 Twig 循环?的主要内容,如果未能解决你的问题,请参考以下文章

警告为错误 - 如何摆脱这些

当AT89S51单片机运行出错或程序陷入死循环时,如何摆脱困境?

我应该如何摆脱循环? [关闭]

我如何摆脱这种无限循环?

铁路围栏密码摆脱循环重复[关闭]

我怎样才能摆脱 chrome 或其他浏览器中的录音符号?