【问题标题】:What is the best way to handle recursion in smarty?在 smarty 中处理递归的最佳方法是什么?
【发布时间】:2009-01-13 03:22:55
【问题描述】:

我在 Smarty 中找到了几种处理递归的方法,主要是基于将模板包含在自身中,这似乎是荒谬的资源浪费。我找到了一个解决方案,由 Messju 在 Smarty 提供,似乎恰到好处 - 但它不受支持并且在最新版本的 smarty 中失败:(

对于有人问:我希望 smarty 打印出一个由条目数组定义的讨论线程。如果一个条目有一个或多个答案,则将这些答案列为数组中所述条目的子项,依此类推。

array(
    array(
        'id'=>0,
        'headline'=>"My parent headline",
        'body'    =>"My parent body",
        'children'=>array(
            array(
                'id'=>1,
                'headline'=>"My firstChild headline",
                'body'    =>"My firstChild body",
                'children'=>array()
            ),
            array(
                'id'=>2,
                'headline'=>"My secondChild headline",
                'body'    =>"My secondChild body",
                'children'=>array()
            )
        )
    ),
);

嵌套数组具有任意深度,每个条目将有任意数量的子项。对我来说,这是我想在模板范围内做的事情,因为我认为它纯粹是显示逻辑。我不想在模板之外处理 HTML 或某种类型的 HTML 占位符。

我希望 smarty 将其打印为嵌套列表:

<ul>
    <li>
        <h1>My parent headline</h1>
        <p>My parent body</p>
        <ul>
            <li>
                <h1>My firstChild headline</h1>
                <p>My firstChild body</p>
            </li>
            <li>
                <h1>My secondChild headline</h1>
                <p>My secondChild body</p>
            </li>
        </ul>
    </li>
</ul>

我开始意识到这可能是一个非常具体的问题,所以我想我会写一个聪明的插件来专门处理这个问题,尽管我宁愿有一个全面的解决方案。

有办法吗?

【问题讨论】:

    标签: php templates recursion smarty


    【解决方案1】:

    在 Smarty 3 中,这可以使用 {function} 来完成。以下代码将产生所需的输出。

    {function name=printList}
    <ul>
        {foreach $items as $item}
        <li>
            <h1>{$item['headline']}</h1>
            <p>{$item['body']}</p>
            {if $item['children']}
                {call name=printList items=$item['children']}
            {/if}
        </li>
        {/foreach}
    </ul>
    {/function}
    
    {call name=printList items=$comments}
    

    更多信息请访问docs

    旁注:仅仅因为某些东西是复杂的或递归的,并不意味着它不能在模板中。看在上帝的份上,HTML ul-li 结构自然是递归的,通过将其隐藏或将其移动到其他地方(只是因为它对于模板来说太复杂了),您将在应用程序中引入额外的复杂性。

    【讨论】:

    • 太棒了!我知道这是一个老问题,但这种方法很棒。 +1
    【解决方案2】:

    “要了解递归,首先要了解递归……”

    开个玩笑。这应该做你想做的事:

    <?php
    /*
    * Smarty plugin
    * ————————————————————-
    * File:     function.recurse_array.php
    * Type:     function
    * Name:     recurse_array
    * Purpose:  prints out elements of an array recursively
    * ————————————————————-
    */
    
    function smarty_function_recurse_array($params, &$smarty)
    {
    
    if (is_array($params['array']) && count($params['array']) > 0) {
       $markup = '';
    
       $markup .= '<ul>';
    
       foreach ($params['array'] as $element) {
          $markup .= '<li>';
    
          $markup .= '<h1>' . $element['headline'] . '</h1>';
          $markup .= '<p>' . $element['body'] . '</p>';
    
          if (isset($element['children'])) {
             $markup .= smarty_function_recurse_array(array('array' => $element['children']), $smarty);
          }
    
           $markup .= '</li>';
       }
    
       $markup.= '</ul>';
    
       return $markup;
    
    } else {
       return 'not array';
    }
    }
    

    将文件放入 smarty/plugins 文件夹。将您的数组分配给 Smarty,然后在您的模板中调用它,如下所示:

    {recurse_array array=$data}
    

    这是制作自定义 Smarty 函数的好教程:

    Creating Custom Smarty Functions

    请注意此示例对您的基础数据结构的依赖性。此外,请记住,异常长或嵌套深度异常的数据集可能会非常慢。管理你的复杂性,把事情记录在案,你应该没问题。祝你好运!

    【讨论】:

      【解决方案3】:

      您可能需要考虑为 smarty 创建自定义函数/修饰符/插件。 将数组传递给自定义函数,同时定义函数应使用的模板。如果就这么简单,只需将文本插入某个位置,在函数中加载模板,并在 PHP 中使用 regexes/str_replace/...

      或者不使用 smarty 模板直接在 PHP 中完成,因为您只需要 h1、ul、li 和 p 标签,并使用 CSS 更改布局。

      或者,如果您担心在 Smarty 中打开和关闭文件的开销,请估计 90% 的情况下的级别数量,并创建涵盖这 90% 的模板。对于其余部分,通过包含模板本身来使用递归......

      【讨论】:

        【解决方案4】:

        最好的办法就是不去做。

        Smarty 应该很简单。这听起来不像。

        【讨论】:

        • 这样想,应用程序需要显示一个任意嵌套的东西列表。那里很复杂。您需要管理复杂性。将本质上是显示逻辑(遍历数组并吐出标记)放在模板中是有意义的。只是递归并不会使它变得邪恶。
        • 很公平,但与使用一次性函数进行递归相比,聪明的解决方案会很复杂。
        猜你喜欢
        • 2017-08-11
        • 2010-09-06
        • 2011-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多