|
 |
Путь: Шпаргалки
Шпаргалки
Автор: - Yurik
Дата публикации - 02.07.2005
Просмотров: - 7675
Отрисовка дерева (tree) с помощью Smarty
Можно красиво сделать используя рекурсивный шаблон, например если есть массив:
[php]
<?php
$foo = array(
'1' => array(
'1.1' => null,
'1.2' => null
),
'2' => null,
'3' => array(
'3.1' => array(
'3.1.1' => null
),
'3.2' => null
)
);
?>[
/php]
Шаблон tree.tpl будет выглядеть так:
[php]
{if $tree}
<ul>
{foreach from=$tree key="name" item="subtree"}
<li>
{$name} {include file="tree.tpl" tree=$subtree}
</li>
{/foreach}
</ul>
{/if}[
/php]
И включайте шаблон в главный master.tpl:
[php]
<h1>Моё дерево</h1>
{include file="tree.tpl" tree=$foo}
[
/php]Если у вас исходный формат массива $foo другой, то можно написать плагин который будет преобразовывать в формат указанный выше
[p]Формат массива[/p]
Как вы могли заметить формат массива который нужно передавать не совсем естественный для деревьев. Это вложенный массив, где названия являются индексами, а значениями - массивы дочерних элементов или [b]null[/b] если таковых нет.
Получаемый из релиционной БД формат дерева - обычно многомерный массив. Конвертация его в нужный формат задача не тривиальная. Допустим есть массив $a[$id]=Array($parentID, $value) и его надо преобразовать
[php]
<?php
$arr[1]=Array(0, '1');
$arr[2]=Array(1, '1.1');
$arr[3]=Array(1, '1.2');
$arr[4]=Array(0, '2');
$arr[5]=Array(0, '3');
$arr[6]=Array(5, '3.1');
$arr[7]=Array(6, '3.1.1');
$arr[8]=Array(5, '3.2');
// в такой вот формат
$foo = array(
'1' => array(
'1.1' => null,
'1.2' => null
),
'2' => null,
'3' => array(
'3.1' => array(
'3.1.1' => null
),
'3.2' => null
)
);
?>
[
/php]
Поскольку рисование дерева мы положили на шаблоны Smarty, то логично и необходимые преобразования реализовать как плагин, который можно вызывать из любого места.
Особая благодарность [url=http://phpclub.ru/talk/member.php?s=&action=getinfo&userid=8]su1d[/url] за помощь в создании алгоритма преобразования
[php]
<?php
/*
* Smarty plugin
* -------------------------------------------------------------
* File: function.treeconvert.php
* Type: function
* Name: treeconvert
* Purpose: Converts array from dimensional to nested format
* -------------------------------------------------------------
*/
function arrSorter($a, $b) {
return $a[0] < $b[0] ? -1 : ($a[0] > $b[0] ? 1 : strcmp($a[1], $b[1]));
}
function smarty_function_treeconvert($params, &$smarty) {
$_arr=$smarty->_tpl_vars[$params['var']];
uasort($_arr, "arrSorter");
$_res = array();
$_parents = array(&$_res);
$_values=Array();
foreach($_arr as $_id => $_pid) {
$_parents[$_pid[0]][$_id] = null;
$_parents[$_id] =& $_parents[$_pid[0]][$_id];
$_values[$_id]=$_pid[1];
}
unset($_parents);
unset($_arr);
$_arr['tree']=$_res;
$_arr['value']=$_values;
unset ($_res);
$smarty->_tpl_vars[$params['var']]=$_arr;
return;
}
?>
[
/php]
И сохранить его в папку $smarty->plugins_dir или в основную plugins папку дистрибутива Smarty.
Шаблоны для вызова этого кода несколько видоизменились:
[b]master.tpl[/b]
[php]
<h1>Моё дерево</h1>
{* передаем в плагин название переменной
которую мы присволили через $s->assign *}
{treeconvert var="foo"}
{include file="tree.tpl" tree=$foo.tree}
[
/php]
[b]tree.tpl[/b]
[php]
{if $tree}
<ul>
{foreach from=$tree key="id" item="subtree"}
<li>
{$foo.value.$id} {include file="tree.tpl" tree=$subtree}
</li>
{/foreach}
</ul>
{/if}
[
/php]
[p]TODO[/p]
Как вы уже заметили, вторая реализация шаблона пока кривовата. Получить сразу массив где в качестве индекса были значения узлов нам не удалось. Поэтому мы передали массив с двумя индексами.
[php]
<?php
$_arr['tree']=$_res; // тут id
$_arr['value']=$_values; // тут привязка ID -> Value
?>
[
/php]
Поскольку к такому массиву напрямую неприменим {foreach}, мы вынуждены в рекурсивном шаблоне обращаться к {$foo.value.$id} чтобы получить знаение соответствующего ID, что есть неправильно.
Так как мы должны указывать имя переменной во вложенном шаблоне такое же как в [b]master.tpl[/b], что делает шаблон не универсальным и не портабельным.
Обсудить в ФОРУМе - комментариев ()
Путь: Шпаргалки
Если вы заметили орфографическую, стилистическую или другую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
|
|