// В БД должно быть 2 таблицы:
// Дерево: tree (id,parent - unsigned int)
// Данные: data (id,name,.. и т.д)
// Связь таблиц по полю id
// Верхний уровень (не имеющий родителей) определяется полем parent = 0
function AL_print_Tree(&$tree) {
// Вывод дерева
// $tree : массив, содержащий дерево
// - предствляет из себя массив со вложенными массивами
// Элементы массива:
// id : идентификатор узла
// parent : родитель узла
// name : данные об узле
// tree : подмассив, содержащий все дочерние узлы, имеющий аналогичную
// структуру - (id,parent,name,tree)
if (empty($tree) || (!is_array($element['tree'])) {
return;
}
echo "<ul>";
foreach ($tree as $element) {
if ((empty($element['parent'])) && (count($tree)>0)) {
echo '<hr />';
}
echo "<li>".$element['name'];
AL_print_Tree($element['tree']);
echo "</li>";
}
echo "</ul>";
}
function AL_load_Node($node) {
// Возвращает в виде массива указанный узел $node
// $node : id узла в таблице БД tree
$res = mysql_query('
SELECT
tree.id, #идентификатор элемента
tree.parent, #идентификатор родительского элемента
# элементы верхнего уровня содержат здесь 0
data.name #название
FROM
tree, #дерево
data #данные
WHERE
tree.id=\''.$node.'\'
and data.id = tree.id
');
if ((!$res) || (false == mysql_num_rows($res))) {
return false;
}
$tree = array();
while (false !== ($row = mysql_fetch_assoc($res))){
$tree[] = array(
'id' => $row['id'],
'parent' => $row['parent'],
'name' => $row['name'],
'tree' => false,
);
}
return $tree;
}
function AL_load_Children($node,$all=false,$depth=1) {
// Рекурсивная функция получения дочерних узлов заданного узла $node
// $node : id узла в таблице БД tree
// $all : флаг возврата всех дочерних узлов
// - true : функция вернет все дочерние узлы массива
// - false: функция вернет дочерние узлы массива на N уровней ниже $node
// $depth : количество уровней дочерних узлов, которые должна вернуть функция
// - 1 : возвращает непосредственные дочерние узлы
// - имеет смысл только при $all = false
if ((!$all) && ($depth < 1)) {
return false;
}
$res = mysql_query('
SELECT
tree.id, #идентификатор элемента
tree.parent, #идентификатор родительского элемента
# элементы верхнего уровня содержат здесь 0
data.name #название
FROM
tree, #дерево
data #данные
WHERE
tree.parent=\''.$node.'\'
and
data.id = tree.id
');
if ((!$res) || (false == mysql_num_rows($res))) {
return false;
}
while (false !== ($row = mysql_fetch_assoc($res))){
$tree[] = array(
'id' => $row['id'],
'parent' => $row['parent'],
'name' => $row['name'],
'tree' => AL_load_Children($row['id'],$all,--$depth),
);
}
if (!empty($tree)) {
return $tree;
} else {
return false;
}
}
function AL_load_Parent($node,$all=false,$depth=1,&$child=false) {
// Рекурсивная функция получения родительских узлов заданного узла $node
// $node : id узла в таблице БД tree
// $all : флаг возврата всех родительских узлов
// - true : функция вернет все родительские узлы массива
// - false: функция вернет родительские узлы массива на N уровней выше $node
// $depth : количество уровней родительских узлов, которые должна вернуть функция
// - 1 : возвращает непосредственный родительский узел
// - имеет смысл только при $all = false
// $child : "внутренняя" переменная, с помощью которой организуется построение
// родительских узлов, начиная с самого верхнего родителя
// - при начальном вызове функции в эту переменную желательно ничего не передавать
// - рекомендуется передавать массив, сформированный с помощью функций
// AL_load_Children, AL_load_Siblings, AL_load_Node, чтобы организовать переопределение
// родительского узла
if ((empty($node)) || ((!$all) && ($depth < 1))) {
return $child;
}
$res = mysql_query('
SELECT
t2.id,
t2.parent,
data.name
FROM
tree as t1 LEFT JOIN
tree as t2 ON
(t2.id = t1.parent),
data
WHERE
t1.id = \''.$node.'\'
and
data.id = t2.id
');
if ((!$res) || (false == mysql_num_rows($res))) {
return $child;
}
while (false !== ($row = mysql_fetch_assoc($res))){
$current = array(
'id' => $row['id'],
'parent' => $row['parent'],
'name' => $row['name'],
'tree' => !$child ? false : array($child),
);
if (!empty($row['parent'])) {
$tree[] = AL_load_Parent($row['id'],$all,--$depth,$current);
}
}
if (!empty($tree)) {
return $tree;
} elseif (!empty($current)) {
return array($current);
} else {
return false;
}
}
function AL_load_Siblings($node,$self=false) {
// Функция получения братских узлов заданного узла $node
// $node : id узла в таблице БД tree
// $self : флаг возврата заданного узла вместе с братскими
// - false: заданный узел не включается в массив
// - true : заданный узел включается в массив
$res = mysql_query('
SELECT
t2.id,
t2.parent,
data.name
FROM
tree as t1 LEFT JOIN
tree as t2 ON
(t2.parent = t1.parent'.($self?'':' and t2.id != t1.id').'),
data
WHERE
t1.id = \''.$node.'\'
and
data.id = t2.id
');
if ((!$res) || (false == mysql_num_rows($res))) {
return false;
}
while (false !== ($row = mysql_fetch_assoc($res))){
$tree[] = array(
'id' => $row['id'],
'parent' => $row['parent'],
'name' => $row['name'],
'tree' => false,
);
}
if (!empty($tree)) {
return $tree;
} else {
return false;
}
}
// Примеры использования функций
// 1. Получение и вывод всего дерева
AL_print_Tree($a_tree = AL_load_Children(0,true));
echo '<hr />';
// 2. Получение и вывод первых двух уровней дерева
AL_print_Tree($a_tree = AL_load_Children(0,false,2));
echo '<hr />';
// 3. Получение и вывод непосредственных дочерних узлов узла с id=2
AL_print_Tree($a_tree = AL_load_Children(2));
echo '<hr />';
// 4. Получение и вывод всех дочерних узлов узла с id=2
AL_print_Tree($a_tree = AL_load_Children(2,true));
echo '<hr />';
// 5. Получение и вывод узла с id=1
AL_print_Tree($a_tree = AL_load_Node(1));
echo '<hr />';
// 6. Получение и вывод братских узлов узла с id=3
AL_print_Tree($a_tree = AL_load_Siblings(3));
echo '<hr />';
// 7. Получение и вывод всех родителей узла с id=4
AL_print_Tree($a_tree = AL_load_Parent(4,true));
echo '<hr />';
// 8. Получение и вывод непосредственного родителя узла с id=4
AL_print_Tree($a_tree = AL_load_Parent(4));