Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][MySQL] Budowanie drzewa
Forum PHP.pl > Forum > PHP
rolnix
Witam.

Zaszła potrzeba utworzenia tablicy drzewa wielopoziomowego za pomocą jak najmniejszej liczby zapytań. Przykładowa tabela:

Kod
id     parent_id    title  
1      0            Artykuły
2      1            Na temat 1
3      1            Na temat 2
4      2            Na podtemat 1
5      2            Na podtemat 2


Celem jest utworzenie tablicy o strukturze:

Kod
Array
(
    [0] => Array
        (
        ["name"] =>  "Artykuły"
        ["items"] => Array
                   (
                         [0] => Array
                         (
                         ["name"] =>  "Na temat 1"
                         ["items"] =>  Array
                                       (
                                             [0] => Array
                                                    (
                                                    ["name"] =>  "Na podtemat 1"
                                                    )
                                             [1] => Array
                                                    (
                                                    ["name"] =>  "Na podtemat 2"
                                                    )
                                       )
                         )
                         [1] => Array
                         (
                         ["name"] =>  "Na temat 2"
                         )
                   )
        )

)


Google podaje mi tylko jakieś wielkie klasy, które operują tylko na memberach obiektu, ew. poprzez rekurencję wykonują więcej zapytań SQL.

Pytanie:

Czy ktoś ma pomysł, jak zbudować takie drzewo z pomocą jednego tylko zapytania, tzn SELECT * FROM categories?
heaven
Jesli masz wyswietlic wszystkie galezie drzewa to musisz pobrac cale drzewo (SELECT * FROM categories) i dzialajac rekurencyjnie na otrzymana tablice zbudowac twoja strukture.
barman
Witam. Sam musiałem sobie poradzić z identycznym problemem kilka dni temu, więc chętnie udzielę pomocy.
Jednorazowy kod można zmieścić w niecałych 30 linijkach, a ubranie go w klasę nie powinno być trudnym zadaniem.

  1. <?php
  2. $AR = new AssocResult ('select * from structure', $DBHandle);
  3. // (ja osobiscie pobieram dane w taki sposob, tutaj nalezy wkleic dowolny kod p
    rzegladajacy wynik wiersz po wierszu)
  4. foreach ($AR as $aVal) {
  5. $Parent = $aVal['parent_id'];
  6. // wstepne ulozenie danych
  7. $Data[$Parent][] = $aVal;
  8. }
  9.  
  10. // $TopID - glowna kategoria drzewa
  11. function BuildStructure ($TopID, $Data) {
  12. $Output = array ();
  13. // sprawdza, czy kategoria zawiera podkategorie
  14. if (! empty ($Data[$TopID])) {
  15. foreach ($Data[$TopID] as $sVal) {
  16. $CurrentRow = $sVal;
  17. // rekurencyjnie buduje podkategorie
  18. $Items = BuildStructure ($sVal['id'], $Data);
  19. if (! empty ($Items)) {
  20. $CurrentRow['items'] = $Items;
  21. }
  22. $Output[] = $CurrentRow;
  23. }
  24. }
  25. return ($Output);
  26. }
  27.  
  28. // zmienna $Output zawiera strukture drzewa
  29. $Tree = BuildStructure (0, $Data);
  30. ?>
em1X
nested tree
dr_bonzo
i inny link http://www.depesz.com/various/various-sqlt...lementation.php
rolnix
Więc kod barmana działa idealnie - wielkie podziękowania smile.gif. Kod mojej wersji:

  1. <?php
  2. function get_all_cats() {
  3. global $sql;
  4. $data = array();
  5. $sql->query('SELECT * FROM ###contentcats');
  6. while ($row = $sql->fetch_array()) {
  7.  $parent = $row['parent_id'];
  8.  $data[$parent][] = array("id"=>$row["id"], "name"=>$row["title"]);
  9. }
  10. return $data;
  11. }
  12.  
  13. function build_cat_tree($top_id, $data, $depth = 1) {
  14. $result = array ();
  15. if (!empty ($data[$top_id])) {
  16. foreach ($data[$top_id] as $sval) {
  17. $currentrow = $sval;
  18. $items = build_cat_tree($sval['id'], $data, $depth+1);
  19. if (!empty($items)) {
  20. $currentrow['items'] = $items;
  21. }
  22. $result[] = $currentrow;
  23. }
  24. }
  25. return ($result);
  26. }
  27.  
  28. $cat_tree = build_cat_tree(0, get_all_cats());
  29. ?>


Jeszcze dla potomności - spłycenie drzewa, czyli przygotowanie danych dla szablonu bez konieczności wywoływania zasobożernej rekurencji w smarty:

  1. <?php
  2. function recurse_cat_flat($cat_tree, $depth, $out) {
  3. $elem = array();
  4. foreach($cat_tree as $cat) {
  5. $elem["title"] = $cat['name'];
  6. $elem["id"] = $cat['id'];
  7. $elem["depth"] = $depth;
  8. array_push($out, $elem);
  9. if (!empty($cat['items'])) recurse_cat_flat($cat['items'], $depth+1, &$out);
  10. }
  11. }
  12.  
  13. function build_cat_flat($cat_tree) {
  14. $result = array();
  15. recurse_cat_flat($cat_tree, 0, &$result);
  16. return $result;
  17. }
  18.  
  19. $cat_flat = build_cat_flat(build_cat_tree(0, get_all_cats()));
  20. ?>
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.