Tree/AlPrintAll

Материал из PhpWiki.

Перейти к: навигация, поиск
 Деревья в базах данных =>  Списки смежности =>  Вывод дерева =>  Вывод всего дерева
Как вывести все дерево?

popoff

скачать форекс клуб

<?php
//1. Загружаем данные. Загружаем в таком виде, в каком они записаны в таблице.
 
$a_tree=array();
//Ключ массива - идентификатор родительского элемента
// значение - список дочерних элементов
 
//Загружаем сразу все дерево одним запросом
$r=mysql_query("
select
t_catalog_tree.k_item, #идентификатор элемента
t_catalog_tree.k_parent, #идентификатор родительского элемента
# элементы верхнего уровня содержат здесь 0
t_catalog.s_name #название
from
t_catalog, #данные
t_catalog_tree #дерево
where
t_catalog.k_item=t_catalog_tree.k_item
order by
t_catalog.s_name");
//Обратите внимание, что в запросе строки отсортированы по s_name.
//Это сделано для того, что бы и сами элементы массива $a_tree и
// списки дочерних элементов этого массива были отсортированы по этому полю.
for($i=0;$i<mysql_num_rows($r);$i++)
{
$f=mysql_fetch_assoc($r);
if(empty($a_tree[$f['k_parent']]))
$a_tree[$f['k_parent']]=array();
$a_tree[$f['k_parent']][]=$f;
}
 
//2. Выводим данные.
 
// Поскольку глубина дерева у нас не ограничена, то логичнее всего
// для вывода использовать рекурсивную функцию.
// Если используемый Вами шаблонный движок это позволяет, то можно
// использовать рекурсивный шаблон.
 
//Обратите внимание на символ "&" перед аргументом $a_tree.
//Я использовал его для того, что бы при каждом рекурсивном вызове
// php не выделял новую память и не копировал туда весь массив $a_tree,
// а только передавал ссылку на исходный массив.
function tree_print(&$a_tree,$k_parent=0)
{
//условие завершения рекурсии
//Условие, при котором функция никогда не вызывает сама себя
 
//функция empty() - вернет ложь во всех нужных нам случаях:
// - элемент массива не определен
// - элемент массива определен, но является пустым массивом
if(empty($a_tree[$k_parent])) return;
 
echo "<ul>";
for($i=0;$i<count($a_tree[$k_parent]);$i++)
{
echo "<li>".$a_tree[$k_parent][$i]['s_name'];
//рекурсивный вызов - список всех дочерних элементов нужно вставить
// именно в этом месте:
// <li>название
// ''тут список дочерних элементов, он показывается рекурсивным вызовом''
// </li>
tree_print($a_tree,$a_tree[$k_parent][$i]['k_item']);
echo "</li>";
}
echo "</ul>";
}
 
//Показываем все дерево:
tree_print($a_tree);
 
?>

Обратите внимание, что в приведенном мной примере вывод дерева никак не зависит от способа хранения дерева (толи это списки смежности, толи это вложенные множества, толи дерево хранится в базе ~MySQL, толи в MSSQL). Нам достаточно только сформировать правильный массив $a_tree и передать его аргументом функции tree_print().

Обратите так же внимание на то, что tree_print() не зависит не только от того, каким способом у нас хранится дерево, но и не зависит от того, какую часть дерева мы хотим вывести. Если мы хотим вывести не все дерево, а только его часть, то нам нужно сформировать массив $a_tree, в котором содержится только нужная нам часть дерева.

Именно из-за такой независимости функции вывода дерева, в нашем случае tree_print() от способа хранения, от используемой базы данных и от того, какую часть дерева мы хотим вывести, вопрос типа "как вывести все дочерние элементы" легко может сбить с толку. Что конкретно Вам не понятно? Вам не понятно, как сделать нужную Вам выборку и сформировать нужный массив или Вам не понятно, как устроена функция tree_print()? Когда Вы задаете вопрос, формулируйте его точно!

Ссылки
Реклама