2009-01-13 128 views
7

我發現了幾種方法來處理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> 

我開始意識到這可能是一個非常逐案的問題,所以我想我會只寫一個智者插件來處理這個具體問題,儘管我寧願有一個全面的解決方案。

有沒有辦法?

回答

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

注意,這個例子對依賴你基礎數據結構。另外,請記住,一個不同尋常的長或深度嵌套組數據可能是非常緩慢的。管理你的複雜性,把事情記錄好,你應該沒問題。祝你好運!

-3

最好的方法是不要這樣做。

Smarty應該很簡單。這聽起來沒有聲音。

+3

想想這樣,應用程序需要顯示一個任意嵌套的東西列表。那裏有複雜性。你需要管理複雜性。在模板中放置基本顯示邏輯(循環遍歷數組並放出標記)是有意義的。只是遞歸不會使它變得邪惡。 – GloryFish 2009-03-16 20:58:46

+0

不夠公平,但與使用一次性函數進行遞歸相比,聰明的解決方案會變得複雜。 – 2009-03-17 04:17:40

0

您可能需要考慮爲smarty創建自定義函數/修飾符/插件。 將數組傳遞給自定義函數,並定義函數應該使用的模板。如果是這樣簡單,只需要將文本插入到某個地方,在模板中加載模板,並使用正則表達式/ str_replace/...

或者直接在PHP中使用不使用smarty模板,因爲所有你需要的是h1,ul,li和p標籤,並且改變佈局使用CSS。

或者,如果你關心的是在Smarty的打開和關閉文件的開銷,估計是什麼的情況下的90%的水平的量,並創建模板,也將覆蓋這些90%。通過包括模板本身...

14

對於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結構是自然遞歸的,通過隱藏它或將它移動到其他地方(僅僅因爲它對於模板來說太複雜),會給應用程序帶來額外的複雜性。

相關問題