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()? Когда Вы задаете вопрос, формулируйте его точно!

Личные инструменты