Форумы портала PHP.SU » » Работа с СУБД » Вывод древовидной структуры из БД

Страниц (2): [1] 2 »
 

1. Saymor - 12 Июля, 2011 - 08:11:44 - перейти к сообщению
вывод данных из БД в виде дерева

есть БД
| id |--------| parent |--------| name |
+----+--------+--------+--------+------------+
| 1 |--------| 0 |--------| Родитель 1 |
| 2 |--------| 0 |--------| Родитель 2 |
| 3 |--------| 0 |--------| Родитель 3 |
| 4 |--------| 0 |--------| Родитель 4 |
| 5 |--------| 0 |--------| Родитель 5 |
| 6 |--------| 0 |--------| Родитель 6 |
| 11 |--------| 1 |--------| Потомок 1 |
| 12 |--------| 1 |--------| Потомок 2 |
| 13 |--------| 2 |--------| Потомок 1 |
| 14 |--------| 13 |--------| Потомок 1 |
| 15 |--------| 13 |--------| Потомок 2 |

выводим данные из БД
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. // делаем запрос
  3. $cats = "SELECT id,name,parent FROM category";
  4.  
  5. // создаем многомерный массив
  6. $tree = array();
  7. for($i=0,$n=count($cats); $i<$n; $i++){
  8.  $cat = $cats[$i];
  9.         if(empty($tree[$cat->parent]))
  10.                 $tree[$cat->parent]=array();
  11.         $tree[$cat->parent][] = $cat;
  12. }
  13.  
  14. // вызываем рекурсивную функцию, передаём ей массив
  15.  ShowCategory($tree);
  16.  
  17. // создаём рекурсивную функцию
  18. function ShowCategory(&$tree,$k_parent=0){
  19.     if(empty($tree[$k_parent])) return;
  20.  
  21.     // выводим дерево
  22.     echo $k_parent ? "<ul>" : "";
  23.     for($i=0,$n=count($tree[$k_parent]); $i<$n; $i++){
  24.       echo "<li>";
  25.         if(??????? кое условие ?????????){ // здесь суть моего вопроса
  26.                 echo "<span>".$tree[$k_parent][$i]->name."</span>";
  27.         }else{
  28.             echo "<a href='index.php?category=".$tree[$k_parent][$i]->id."'>".$tree[$k_parent][$i]->p_name."</a>";
  29.         }
  30.  
  31.         // функция вызывает сама себя с массивом $tree и $tree[$k_parent][$i]->id родителя
  32.         ShowCategory($tree, $tree[$k_parent][$i]->id);
  33.       echo "</li>";
  34.     }
  35.     echo $k_parent ? "</ul>" : "";
  36. } ?>


Пожалуйста помогите создать условие.
поясню: в результате самый последний потомок должен быть ссылкой, любой родитель нет.
2. DeepVarvar - 12 Июля, 2011 - 09:01:00 - перейти к сообщению
Что-то типа:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT * FROM category ORDER BY id ASC GROUP BY parent
3. Saymor - 12 Июля, 2011 - 13:08:43 - перейти к сообщению
DeepVarvar пишет:
Что-то типа:
CODE (SQL):
скопировать код в буфер обмена

SELECT * FROM category ORDER BY id ASC GROUP BY parent




спасибо, но это НЕ то....
Мне кажется модераторы перенесли тему не в ту степь!
Тема моего сообщения затрагивает "Рекурсию", а не БД!
4. OrmaJever - 12 Июля, 2011 - 13:46:42 - перейти к сообщению
нет тема какраз таки затрагивает бд. Вы просто изначально не верно написали.
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. // вызываем рекурсивную функцию, передаём ей массив
  4.  ShowCategory(0);
  5.  
  6. // создаём рекурсивную функцию
  7. function ShowCategory($parent = 0){
  8.  
  9.          $q = mysql_query("SELECT id,name,parent FROM category WHERE parent = $parent");
  10.     if(mysql_num_rows($q) == 0) return;
  11.  
  12.     // выводим дерево
  13.     echo "<ul>";
  14.  
  15.     while($ob = mysql_fetch_object($q)) {
  16.       echo "<li>";
  17.       echo "<a href='index.php?category=".$ob->id."'>".$ob->name."</a>";
  18.       ShowCategory($ob->id);
  19.       echo "</li>";
  20.     }
  21.     echo "</ul>";
  22. }
  23. ?>

Вроде верно, но мог и гдето ошибится
(Добавление)
только что проверил
5. Saymor - 12 Июля, 2011 - 13:59:35 - перейти к сообщению
OrmaJever пишет:
нет тема какраз таки затрагивает бд. Вы просто изначально не верно написали.
PHP:
скопировать код в буфер обмена

<?PHP

// вызываем рекурсивную функцию, передаём ей массив
ShowCategory(0);

// создаём рекурсивную функцию
function ShowCategory($parent = 0){

$q = mysql_query("SELECT id,name,parent FROM category WHERE parent = $parent");
if(mysql_num_rows($q) == 0) return;

// выводим дерево
echo "<ul>";

while($ob = mysql_fetch_object($q)) {
echo "<li>";
echo "<a href='index.php?category=".$ob->id."'>".$ob->name."</a>";
ShowCategory($ob->id);
echo "</li>";
}
echo "</ul>";
}
?>


Вроде верно, но мог и гдето ошибится



хм. Ваш подход ведет к множеству запросов к БД, а это не приемлемо если у нас дерево неограниченной вложенности.
Мой код в начале темы делает всего 1 запрос к БД, далее работаем только с массивом, сортируя его так чтоб вышло дерево.. и все работает, вот только с условием беда...
с выводом ссылки конечного потомка
6. OrmaJever - 12 Июля, 2011 - 14:37:42 - перейти к сообщению
Saymor пишет:
Ваш подход ведет к множеству запросов к БД

Да это так но не факт что с вариант с масивом будет лутше.
Цыкл который делает этот масив потянет время + если неограниченая вложеность то сам масив потянет большую память.
7. Saymor - 12 Июля, 2011 - 14:54:52 - перейти к сообщению
OrmaJever пишет:
Да это так но не факт что с вариант с масивом будет лутше.
Цыкл который делает этот масив потянет время + если неограниченая вложеность то сам масив потянет большую память.


ну даже не знаю что сказать!
в целом массив кэшировать можно, так же как и запросы к БД,,,,
Однако читал, что 1 запрос лучше. Не думаю что массив нагнет сервак больше чем множественные запросы к БД..
8. OrmaJever - 12 Июля, 2011 - 16:03:16 - перейти к сообщению
Saymor пишет:
Однако читал, что 1 запрос лучше.

Да один запрос лутше чем много но смотря с чем сравнивать.
Saymor пишет:
Не думаю что массив нагнет сервак больше чем множественные запросы к БД

Это спорный вопрос и зависит от вложености.
9. Saymor - 12 Июля, 2011 - 16:51:20 - перейти к сообщению
OrmaJever пишет:
Это спорный вопрос и зависит от вложености.


думаю вложенность будет максимум 4 - 5 уровней
10. OrmaJever - 12 Июля, 2011 - 17:02:26 - перейти к сообщению
Запросов много не будет. Вот для даного примера их будет всего 4
первый - красный
второй - зелёный
трейтий - синий
четвёртый - жолтый


Может ещё кто-то другой выскажет своё мнение по этому поводу Улыбка
11. Мелкий - 12 Июля, 2011 - 17:08:32 - перейти к сообщению
OrmaJever, вообще-то 4 - это будет результатов.
А запросов будет 11. Без запроса не узнаешь, есть ли дочерние элементы.

Saymor, возможно, условие будет isset($tree[$id]), если я правильно понял исходник.
12. Саныч - 12 Июля, 2011 - 17:17:11 - перейти к сообщению
OrmaJever пишет:
Может ещё кто-то другой выскажет своё мнение по этому поводу
А что тут высказывать, вы уже и так все растолковали...
Оба вариант имеют свои плюсы и свои минусы, и оптимального решения нет... Тут нужно выбирать меньшее зло... Исходя из задачи которую необходимо реализовать...

OrmaJever пишет:
Запросов много не будет. Вот для даного примера их будет всего 4
Не факт... Это смотря какая вложенность планируется и количество самих элементов... Пример из личного опыта: когда-то сделал знакомому менюшку на рекурсии. В итоге когда он все это дело наполнил, получилось, что местами вложенность достигала 6 - 7 уровня. В итоге - почти полсотни запросов к БД.

Saymor, если это что-то типа менюхи, то вначале выводите только родителей, а дальше уже аяксом подгружать потомков по кликам на родителей...
(Добавление)
Мелкий пишет:
Без запроса не узнаешь, есть ли дочерние элементы
а это и не нужно узнавать... Делается запрос на выборку элементов, а проверка наличия - по количеству выбраных результатов
13. Мелкий - 12 Июля, 2011 - 17:20:17 - перейти к сообщению
Саныч пишет:
Делается запрос на выборку элементов, а проверка наличия - по количеству выбраных результатов

А эт типа не запрос? Так, из астрала, тягаем данные?
14. Саныч - 12 Июля, 2011 - 17:25:46 - перейти к сообщению
Это к тому, что
Цитата:
вообще-то 4 - это будет результатов.
А запросов будет 11
запросов тоже будет 4!
15. Мелкий - 12 Июля, 2011 - 17:30:14 - перейти к сообщению
Саныч, посыплю голову пеплом и признаю, что я дурак и делать мне в программировании нечего, если докажешь, что следующее неверно:
Представленный чуть ранее код OrmaJever'а делает запрос для каждого элемента списка. Сколько элементов - столько и запросов.

Рекурсивная функция осуществляет запрос и в цикле обхода результата вызывается рекурсивно => для каждого элемента производится запрос к базе.
Вот если бы было поле в записи родителя типа "у меня есть дети, смотри далее" и оно проверялось перед вызовом рекурсии - да, запросов было бы столько, сколько элементов имеют детей.

 

Powered by ExBB FM 1.0 RC1