Каков наилучший способ обработки рекурсии в smarty?

Я нашел несколько способов обработки рекурсии в 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>

Я начинаю поймите, что это может быть очень случайная проблема, поэтому я думаю, что просто напишу плагин smarty, чтобы справиться с этим конкретно, хотя я предпочел бы иметь всестороннее решение.

есть ли способ?

4 ответов


"чтобы понять рекурсию, нужно сперва понять рекурсию..."

шучу. Это должно делать то, что вы хотите:

<?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:

Создание Пользовательских Функций Smarty

имейте в виду зависимость, что это пример имеет базовую структуру данных. Кроме того, имейте в виду, что необычно длинный или глубоко вложенный набор данных может быть очень медленным. Управляйте своей сложностью, держите вещи хорошо документированными, и вы должны быть в порядке. Удачи!


С помощью 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 естественно рекурсивна, и, скрывая ее или перемещая в другое место (просто потому, что она слишком сложна для шаблона), вы введение дополнительной сложности в приложение.


возможно, вы захотите создать пользовательскую функцию / модификатор / плагин для smarty. Передайте массив пользовательской функции вместе с определением шаблона, который должна использовать функция. Если это так просто, только для вставки текста в определенное место, загрузите шаблон внутри функции и в PHP работайте с шаблоном, используя regexes/str_replace/...

или сделать это непосредственно в PHP без использования шаблонов smarty, потому что все, что вам нужно, это H1, ul, li и P теги и изменить макета использовать CSS.

или если ваша забота накладные расходы с открытием и закрытием файлов в Smarty, оценить, какое количество уровней в 90% случаев и создать шаблон, который будет охватывать эти 90%. Для остальных используйте рекурсию, включив сам шаблон...


лучший способ-не делать этого.

Smarty должен быть простым. Этот deesn не звучит.