我找到了几种方法来处理Smarty中的递归,主要是基于将模板包含在自身中,这似乎是荒谬的资源浪费。我找到了一个解决方案,由Messju在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占位符。
我想要巧妙地将其打印为嵌套列表:
<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>
我开始意识到这可能是一个非常具体的问题,所以我想我会写一个聪明的插件来专门处理这个问题,尽管我宁愿有一个全面的解决方案。 / p>
有办法吗?
答案 0 :(得分:16)
使用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 :(得分:6)
“为了理解递归,你必须先了解递归......”
开玩笑吧。这应该做你想要的:<?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
请注意此示例对基础数据结构的依赖性。另外,请记住,异常长或嵌套的数据集可能非常慢。管理你的复杂性,记录好文档,你应该没事。祝你好运!
答案 2 :(得分:0)
您可能需要考虑为smarty创建自定义函数/修饰符/插件。 将数组传递给自定义函数以及定义函数应使用的模板。如果这么简单,只将文本插入到某个地方,在模板中加载模板,在PHP中使用regexes / str_replace / ...模板工作。
或者直接在PHP中使用智能模板,因为您只需要h1,ul,li和p标签,并使用CSS更改布局。
或者,如果你关注的是在Smarty中打开和关闭文件的开销,估计90%的案例中的级别数量,并创建将覆盖90%的模板。对于其余的使用递归,包括模板本身......
答案 3 :(得分:-4)
最好的方法是不要这样做。
Smart应该很简单。这听起来不是。