Неограниченная вложенность структур и Smarty

nw

Новичок
Неограниченная вложенность структур и Smarty

Что-то не могу собразить. Как в Smarty можно вывести иерархическую структуру с неограниченным количеством вложенных элементов? Простой пример:
Есть вполне стандартная таблица в БД, где хранятся группы товаров. Упрощенно, поля в таблице такие:
id, name, prev_id. Где соответственно prev_id это id родительской группы товаров.
Задача: вывести на экран дерево групп товаров (используя смарти).
У меня возникают трудности:
1) Если количество вложенных уровней известно заранее, то конечно проблем нет, просто нужное количество раз в шаблоне пропишем <{foreach}>, но тут уровней может быть n.
2) Если генерить html сразу (без смарти), то понятно дело, можно написать функцию (генерящую HTML) и использовать ее рекурсивно, но как это сделать в смарти?
3) Все осложняется тем, что необходимо для разных уровней вложенности использовать свои шаблоны, т.е. например, все группы товаров самого верхнего уровня должны выводиться в отдельных сторках таблицы (<tr><td>{$item.name}), второй уровень вложенности должен выводиться, например, как "{$item.name}<br>".
Резюме: как реализовать получение и отображение иерархической структуры с неограниченным количеством уровней вложенности с помощью Smarty?
 

Demiurg

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

nw

Новичок
Если для каждого уровня свой шаблон
Да, пожалуй опустим вариант с разными шаблонами для каждого уровня, тут нужен отдельный разговор. Будем предполагать, что каждый уровень выводится одинаково с помощью <tr><td> и некоторого количества nbsp.
Данные в каком виде приходят в smarty ?
Это часть моего вопроса. Изначально есть БД-таблица (я привел пример ее структуры выше). Т.е. вопрос как раз в том, в каком виде данные лучше всего получить из БД и как эти данные лучше отобразить?
 

Demiurg

Guest
Если данные передаются в виде:
array(
array('level'=>1 , 'name'=>'name1') ,
array('level'=>1 , 'name'=>'name2') ,
array('level'=>2 , 'name'=>'name21') ,
array('level'=>3 , 'name'=>'name211') ,
array('level'=>1 , 'name'=>'name3') ,
....
)

то никаких проблем не вижу, один цикл.
 

nw

Новичок
то никаких проблем не вижу, один цикл
В этом случае не совсем ясно, как можно отобразить иерархию? Возможно я просто притормаживаю. Задача не просто обозначить уровень, а так же всю иерархию (дерево).
 

Demiurg

Guest
например так:
{foreach from = $arr item = i}
{"&nbsp;"|str_repeat:$i.level}{$i.name}<br>
{/foreach}
 

nw

Новичок
Спасибо! Собразил. Тут один из ключевых моментов был - порядок элементов в исходном массиве. Для его формирования я использовал рекурсию (чтобы очередность была правильной с точки зрения иерархии: родитель1-наследник11, родитель2-наследник21-наследник211...).
После формирования этого массива остается только в смарти при переборе элементов применять либо {"&nbsp;"|str_repeat:$i.level} (для обозначения отступов в дереве посредством пробелов) или, к примеру, с помощью CSS class="level{$i.level}" или заголовков <h{$i.level}>.

-~{}~ 11.04.05 10:26:

В подзабытую тему снова вопрос. Что-то идей толком пока нет.
Есть массив вида:
PHP:
$array1 = array (
    "name" = "name_of_array1",
    "children" = $array2
);
При этом, массив $array2 имеет ту же структуру что и $array1. Т.е. есть массив $array1 с заранее неизвестным количеством вложенных однотипных массивов.
Вопрос: как в смарти организовать вывод этого массива в структуру типа:
PHP:
<ul>
    <li>name_of_array1
    <ul>
        <li>name_of_array2
        ...</li>
    </ul>
    </li>
</ul>
 

Yaguan

пилот
nw
Не так давно решал такую же задачу.

Имхо, здесь без рекурсии не обойтись, поэтому пришлось в скрипте писать рекурсивную функцию, которая отрисовывала дерево в переменную, используя $smarty->fetch(). Уже готовое дерево передавалось в основной шаблон.
 

crocodile2u

http://vbolshov.org.ru
хм... А если в шаблоне tree_level.tpl сделать по определенному условию (наличие потомков) - {include file=tree_level.tpl} - включать самого себя?

Если массив сформирован нужным образом, должно прокатить. Хотя сам не пробовал. Предпочитаю NestedSets, и никакой рекурсии не нужно

-~{}~ 11.04.05 12:03:

Блин, только сейчас заметил, что тема-то уже древняя...
 

Yaguan

пилот
crocodile2u
хм... А если в шаблоне tree_level.tpl сделать по определенному условию (наличие потомков) - {include file=tree_level.tpl} - включать самого себя?

Если массив сформирован нужным образом, должно прокатить. Хотя сам не пробовал.
Спасибо за идею, переделал свое решение таким образом, вроде бы все нормально.
 

crocodile2u

http://vbolshov.org.ru
Вообще-то надо бы еще посмотреть, каким образом смарти обрабатывает директиву include. Если реально инклюдится скомпайленный файл на каждый такой вызов, то, кто его знает, не начнутся ли тормоза при большом дереве с высоким уровнем вложенности. получается - рекурсивно инклюдим файл большое количество раз.
 

Yaguan

пилот
Посмотрел Smarty.class.php. Действительно, внутри метода _smarty_include() инклудится скомпиленный файл шаблона.

Все равно, я больше рад, что удалось убрать ненужную логику из скрипта в шаблон, а производительность в моем случае - дело второстепенное.
 
Сверху