Каков наилучший способ обработки рекурсии в 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, чтобы справиться с этим конкретно, хотя я бы предпочел бы использовать всестороннее решение.

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

«Чтобы понять рекурсию, вы должны сначала понять рекурсию …»

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

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

Более подробную информацию можно найти в документах .

Боковое примечание. Просто потому, что что-то сложно или рекурсивно, это не значит, что оно не может быть внутри шаблона. Ради Бога структура HTML ul-li, естественно, рекурсивна и, скрывая ее или перемещая ее в другое место (только потому, что она слишком сложна для шаблона), вы вводите дополнительную сложность в приложение.

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

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

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

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

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