Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problem z drzewem kategorii
Forum PHP.pl > Forum > PHP
majestiq
Witam,

Chciałbym w jakiś prosty sposób korzystać z drzewa kategorii.
W bazie, tabela kategorie ma takie parametry:

id
nazwa_kategorii
kategoria_nadrzędna

Jeśli kategoria jest główna (na samej górze) to kategoria_nadrzędna = 0

Do rysowania używam czegoś takiego:

  1. <?php
  2.  
  3.  
  4.  
  5. // BUDOWANIE MENU        
  6. // 1 PRZEBIEG, WCZYTANIE KATEGORII    
  7.  
  8.    $catt = $_GET['catid'];    
  9.  
  10.    $wczytaj_kategorie = "SELECT * FROM kategorie WHERE cat_parent=0";
  11.    $answ = mysql_query($wczytaj_kategorie, $conn);
  12.    
  13.            while($rek = mysql_fetch_array($answ)) {
  14.                  $nazwak = $rek['cat_name'];
  15.                  $idkat = $rek['cat_id'];
  16.                    echo $nazwak;
  17.            
  18.                // 2 PRZEBIEG, WCZYTANIE PLIKOW Z DANEJ KATEGORII    
  19.                $wczytaj_kategorie_2 = "SELECT * FROM kategorie WHERE cat_parent=$idkat";
  20.                $answ2 = mysql_query($wczytaj_kategorie_2, $conn);
  21.                      echo "<ul>";
  22.  
  23.    
  24.            while($rek = mysql_fetch_array($answ2)) {
  25.                  $nazwakategorii = $rek['cat_name'];
  26.                   $idkategorii = $rek['cat_id'];
  27.                  
  28.                             if ($catt==$idkategorii || $kategoria_pliku==$idkategorii) {
  29.                       echo "<li style='font-family:arial; color:#ff0000;'><a href='plik.php?catid=" . $idkategorii . "'>"  . $nazwakategorii . "</a></li>";
  30.                        }
  31.                    else {
  32.                        echo "<li style='font-family:arial; color:#ccc;'><a href='plik.php?catid=" . $idkategorii . "'>"  . $nazwakategorii . "</a></li>";
  33.  
  34.                    }
  35.        
  36.                    
  37.            }
  38.  
  39.                                  echo "</ul>";
  40.        
  41.            }
  42. ?>



Jednak to działa tylko dla jednej kategorii podrzędnej (Kategoria główna -> podkategoria -> pliki z danej podkategorii)
Docelowo chciałbym aby można było dobrać się do większej ilości podkategorii (5 by spokojnie wystarczyło) tylko jak to zrobić, żeby było ok?

Czytałem coś o nested tree itp, ale coś nie idzie mi implementacja tego.
Może jest jakiś fajny prosty sposób ?
wlamywacz
Do poczytania:
http://www.depesz.com/various/various-sqltrees.php
cichy380
Podam Ci poprostu moją metodę uważam najbardziej optymalną i najprostrzą na jaką wpadłem, a jaką używałem sam wielokrotnie.

Kod
   <?php
     $tree = array(); // tu bedziemy przechowywac cale drzewko kategorii
    
     // jedno proste zapytanie wyciagajace wszystkie kategorie - bardziej optymalnie
     $q = 'SELECT * FROM kategorie';
     $res = mysql_query($q, $conn);
  
     // jedna petla do utworzenia zmiennej tablicowej ($tree) zawierajacej uporzadkowana strukture drzewka kategorii
     while($row = mysql_fetch_array($res)) {
         $tree[ $row['cat_parent'] ][] = array('id' => $row['cat_id'], 'name' => $row['cat_name']);
     }
    
     // funkca rekurencyjna "wypisujaca" nasze drzewko (generujaca odpowiedni HTML z <UL/><LI/>)
     function tree_generator($array_tree, $root_id=0) {
    
         $return_html = '';
    
         if( isset($array_tree[$root_id]) ) {
         $return_html .= '<ul>';
            foreach($array_tree[$root_id] as $array_tree_values) {
                 $return_html .= '<li>' . $array_tree_values['cat_name'];
            }
            $return_html .= tree_generator($array_tree, $array_tree_values['cat_id']); // rekurencja - jezeli dana kategoria ma podkategorie funkcja zwroci kolejne zagniezdzone <ul/><li/>
            $return_html .= '</li>';
         }
         $return_html .= '</ul>';
    
         return $return_html;
     }
    
     echo tree_generator($tree);
   ?>


pisałem z palca więc mogą być tu jakieś drobne pomyłki, ale chyba kod jest dość prosty i czytelny i jasno przedstawia o co mi chodzi
majestiq
Coś mi to nie działa do końca.
Wynik w html:

<ul><li><li><li><li><li><li></ul></li></ul>
wlamywacz
Nie zrobisz tego z takiej struktury tabeli, do tego potrzeba informacji na jakim poziomie zagłębienia znajduje się dany element.
majestiq
To jak to zrobić ?
pinochet
robisz sobie kolumne deep i potem w SQL-u WHERE deep >= $current_deep
majestiq
Próbowalem przerobic inny skrypt i wyszlo mi cos takiego:

  1. <?php
  2.  
  3. require "functions.php";
  4. require "mysql.php";
  5.  
  6. $filee = $skr_sql->query($db, "SELECT * FROM pliki WHERE file_id = '$id'", 1);
  7. $config = $skr_sql->query($db,"SELECT * FROM pafiledb_settings",1);
  8.  
  9. $db[prefix] = 'kategorie';
  10. $tmp_query = $_ENV['QUERY_STRING'];
  11. $category = $skr_sql->query($db, "SELECT * FROM $db[prefix] WHERE cat_id = '$id'", 1);
  12. if ($category[2] == 0) { $locbar = "<a href=\"catpafile.php\" class=\"small\">$config[1]</a> :: <a href='?$tmp_query'> $category[1]</a>"; }
  13. if ($category[2] > 0) {
  14.    $parent = $skr_sql->query($db, "SELECT * FROM $db[prefix] WHERE cat_id = '$category[2]'", 1);
  15.    $locbar = "<a href=\"catpafile.php\" class=\"small\">$config[1]</a> :: <a href=\"catpafile.php?action=category&id=$parent[0]\" class=\"small\">$parent[1]</a> :: <a href='?$tmp_query'> $category[1]</a>";
  16. }
  17. if ($logged == 1) {
  18.    adlocbar($locbar, $user,$str);
  19.    adminlinks_viewcat($str,$id);
  20. } else {
  21.    locbar($locbar);
  22. }
  23. $result = $skr_sql->query($db, "SELECT * FROM $db[prefix] WHERE cat_parent = '$id' ORDER BY cat_id", 0);
  24. $n = mysql_num_rows($result);
  25. if ($n > 0) {
  26.    echo("<table width=\"100%\" border=\"1\" cellpadding=\"2\" cellspacing=\"0\" class=\"headertable\" bordercolor=\"#000000\">
  27.        <tr><td width=\"90%\" class=\"headercell\"><center><b>$str[category]</b></center></td><td width=\"10%\" class=\"headercell\"><center><b>$str[files]</td></tr>");
  28.    #$result = $skr_sql->query($db, "SELECT * FROM $db[prefix] WHERE cat_parent = '$id' ORDER BY cat_id", 0);
  29.    while ($sub = mysql_fetch_object($result)) {
  30.        $filesincat = $skr_sql->query($db, "SELECT * FROM pliki WHERE file_cat = '$sub->cat_id'", 2);
  31.        echo "<tr><td width=\"90%\" class=\"datacell\"><a href=\"catpafile.php?action=category&id=$sub->cat_id\">$sub->cat_name</a><br><a class=\"smalltext\">&raquo; $sub->cat_desc &laquo;</a></td><td width=\"10%\" class=\"datacell\"><center>$filesincat</center></td></tr>";
  32.    }
  33.    echo"</table><p>";
  34. }
  35. $result = $skr_sql->query($db, "SELECT * FROM pliki WHERE file_cat = '$id' AND file_pin = '1' ORDER BY file_id", 0);
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43. while ($file = mysql_fetch_object($result)) {
  44.    $date = date("n/j/y", $file->file_time);
  45.    $ntv = $file->file_totalvotes - 1;
  46.    if ($file->file_rating == 0 or $ntv == 0) { $rating = 0; } else {$rating = round($file->file_rating/$ntv, 2); }
  47.    if ($file->file_posticon == "none" or $file->file_posticon == "none.gif") {
  48.        $posticon = "&nbsp;";
  49.    } else {
  50.        $posticon = "<img src=\"images/posticons/$file->file_posticon\">";
  51.    }
  52.    $filelist .= "<tr><td width=\"5%\" align=\"center\" class=\"datacell\">$posticon</td><td width=\"65%\" class=\"datacell\"><a href=\"catpafile.php?action=file&id=$file->file_id\">$file->file_name</a><br><a class=\"smalltext\">&raquo; $file->file_desc &laquo;</a></td><td width=\"10%\" class=\"datacell\"><center>$date</center></td><td width=\"10%\" class=\"datacell\"><center>$rating/10</center></td><td width=\"10%\" class=\"datacell\"><center>$file->file_dls</center></td></tr>";
  53. }
  54. $numpages = ceil($filesincat / 35);
  55. if ($start + 35 < $filesincat) {
  56.    $newstart = $start + 35;
  57.    $next = "<a href=\"catpafile.php?action=category&id=$id&start=$newstart&sortby=$sortby\">$str[next] &raquo;</a>";
  58. }
  59. if ($start - 35 >= 0) {
  60.    $newstart = $start - 35;
  61.    $prev = "<a href=\"catpafile.php?action=category&id=$id&start=$newstart&sortby=$sortby\">&laquo; $str[prev]</a>";
  62. }
  63. for ($i = 0; $i < $numpages; $i++) {
  64.    $newstart = 35*$i;
  65.    $pagenum = $i + 1;
  66.    if ($newstart == $start) {
  67.        $pages .= "$pagenum ";
  68.    } else {
  69.        $pages .= "<a href=\"catpafile.php?action=category&id=$id&start=$newstart&sortby=$sortby\">$pagenum</a> ";
  70.    }
  71. }
  72. $filelist = trim($filelist);
  73. if (!empty($filelist)) {
  74.    ?>
  75.    <table width="450px" border="1" cellpadding="2" cellspacing="0" class="headertable" bordercolor="#cccccc">
  76.    <tr><td width="5%" class="headercell"></td><td width="65%" class="headercell"><center><b><?php echo $str[file]; ?></b></center></td><td width="10%" class="headercell"><center><b><?php echo $str[date]; ?></b></center></td><td width="10%" class="headercell"><center><b><?php echo $str[rating]; ?></b></center></td><td width="10%" class="headercell"><center><b><?php echo $str[dls]; ?></b></center></td></tr>
  77.    <?php
  78.    echo $filelist;
  79.    ?>



Wystarczy, że będzie można dodać jeszcze tylko 1 poziom i starczy.

Narazie jest: Poziom1 -> Poziom2 -> Content dla poziom2
Chciałbym zeby bylo chociaż Poziom1 -> Poziom2 -> Poziom3 -> Content dla poziom2

Nie będe potrzebował więcej Poziomów niż 3 no góra 4.
wlamywacz
Zastosuj metodę zagnieżdżonych zbiorów która jest bardzo prosta.
majestiq
Przeczytałem sobie to: http://www.depesz.com/index.php/2007/01/20...zonych-zbiorow/
ale nie dam rady tego zaimplementować a co dopiero później wykonywać na tym jakichś updatów itp.


Chciałbym użyć tego skryptu, tylko coś musiałem źle wstawić bo mi wywala:

Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in /home/mp4/ftp/skrypty/plikz2/kateg.php on line 11



  1. <?php
  2.  
  3.  
  4.  
  5. function pokazWszystkieKategorieDrzewko($idKategorieNadrzedna, $ileKategorii){        
  6.  
  7.      echo'<ul>';
  8.        $i = 1;
  9.        $res = mysql_query('SELECT * FROM kategorie WHERE cat_parent='.$idKategorieNadrzedna.' ORDER BY kolejnosc ASC, nazwa ASC');  
  10.        while($row = mysql_fetch_assoc($res)){
  11.        
  12.                echo'<li>';
  13.                echo'<a href="index.php?idKategorieWybrana='.$row['idKategorie'].'">'.$row['nazwa'].'</a>';        
  14.                
  15.                //sprzwdzam czy ma podkategorie
  16.                $res1 = mysql_query('SELECT COUNT(*) AS ileKategorii FROM kategorie WHERE idKategorieNadrzedna='.$row['idKategorie']);
  17.                $row1 = mysql_fetch_assoc($res1);
  18.                if($row1['ileKategorii'] > 0){//jeśli ma podkategorie
  19.                
  20.                        pokazWszystkieKategorieDrzewko($row['idKategorie'],$row1['ileKategorii']);    
  21.                }            
  22.                echo'</li>';
  23.                
  24.                if($i == $ileKategorii){//jeśli sparsowałem ostatnią
  25.                        echo'</ul>';
  26.                }else{
  27.                        $i++;
  28.                }                
  29.        }    
  30. }
  31.  
  32.  
  33. //WYWOŁANIE FUNKCJI
  34. //pobieram ilość kategorii głównych - tych z poziomem 0 jako nadrzędna
  35. $res = mysql_query('SELECT COUNT(*) AS ileKategorii FROM kategorie WHERE cat_parent = 0');
  36. $row = mysql_fetch_assoc($res);        
  37. pokazWszystkieKategorieDrzewko(0,$row['ileKategorii']); // (idKategorieNadrzedna, $ileKategorii)
  38. ?>



Struktura tabeli kategorie:

cat_id
cat_name
cat_parent

Proszę o pomoc.
cichy380
Cytat(majestiq @ 6.01.2009, 22:29:39 ) *
Coś mi to nie działa do końca.
Wynik w html:

<ul><li><li><li><li><li><li></ul></li></ul>


źle pętle FOREACH zamknąłem, powinno być

Kod
function tree_generator($array_tree, $root_id=0) {
        
            $return_html = '';
        
            if( isset($array_tree[$root_id]) ) {
               $return_html .= '<ul>';
               foreach($array_tree[$root_id] as $array_tree_values) {
                   $return_html .= '<li>' . $array_tree_values['cat_name'];
                   $return_html .= tree_generator($array_tree, $array_tree_values['cat_id']);
                   $return_html .= '</li>';
               }
               $return_html .= '</ul>';
            }
        
            return $return_html;
        }


a co do przechowywania poziomu zagłębienia w bazie danych to może to nieznacznie przyspieszyć działanie całości (wyciągać tylko potrzebne kategorie (np. pierwszego i drugiego poziomu)), ale jest bardziej skomplikuje.

Ale moją funkcję (tree_generator()) można udoskonalić o jakąś "blokade" - np. dodatkowy atrybut jaki będzie przyjmowała sugerujący jej do jakiego poziomu zagłębienia ma generować kod HTML
nospor
Cytat
Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource


Kurcze... 150 postow i jeszcze z czyms takim problem?

Tu masz napisane jak sie analizuje takie "powazne" bledy
http://nospor.pl/php-faq-n29.html#faq-6
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.