Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Wielopoziomowe Menu
Forum PHP.pl > Forum > Przedszkole
sliwa007
Na wstępie mówię że szukałem w google ale nie znalazłem przykładu który mógłbym mi pomóc. Potrzebuję stworzyć wielopoziomowe menu w którym można tworzyć podkategorie w nieskończoność i nie mam pojęcia jak skonstruować taki skrypt.

Baza danych:

| id | | parent_id | | name | | url | | type | | menu | | poziom |
| 1 | | 0 | | Link 1 | | link1 | | page | | main_menu | | 0 |
| 2 | | 0 | | Link 2 | | link2 | | page | | main_menu | | 0 |
| 3 | | 1 | | Sub Link 1 | |sublink1 | | page | | main_menu | | 1 |
| 4 | | 1 | | Sub Link 2 | | sublink2 | | page | | main_menu | | 1 |
| 5 | | 3 | | trzeci rząd | | 3rzad | | page | | main_menu | | 2 |


Napisałem coś takiego, ale niestety zagłębia się tylko w 2 poziomy ntomiast chcę zrobić tak żeby poziomów było tyle ile użytkownik będzie chciał. Proszę po podpowiedź jak to można zrobić bo nie mam pojęcia jak skonstruować kod:
  1. function menu($menu) {
  2. //wybieranie menu
  3. $query_menu = mysql_query("SELECT * FROM menus WHERE name = '$menu'");
  4. $query_menu = mysql_fetch_assoc($query_menu);
  5. $menu_name = $query_menu['name'];
  6.  
  7. //pobieranie pozycji menu
  8. $query_menu_poz = mysql_query("SELECT * FROM menu_poz WHERE menu = '$menu_name' AND parent_id = '0'");
  9.  
  10. while($query_menu_p = mysql_fetch_assoc($query_menu_poz)) {
  11. $id_pozycji = $query_menu_p['id'];
  12. $query_sub = mysql_query("SELECT * FROM menu_poz WHERE parent_id = '$id_pozycji'");
  13. $ile_sub = mysql_num_rows($query_sub);
  14.  
  15. //pobieranie subkategorii
  16. if($ile_sub == 0) {
  17. $link.= $query_menu_p['name'].'<br/>';
  18. } else {
  19. while($query_sub_p = mysql_fetch_assoc($query_sub)) {
  20. $sublink.= '-'.$query_sub_p['name'].'<br>';
  21. }
  22. $link.= $query_menu_p['name'].'<br/>'.$sublink;
  23. }
  24. }
  25.  
  26.  
  27. return $query_menu['desc'].'<br/>'.$link;
  28. }
grzeee
Poczytaj o rekurencji. Zbuduj funkcję która wykorzystasz w tejże funkcji.
W takim mały skrócie:
  1. function twoja_funkcja(){
  2. if($children) {
  3. // wykonujesz jeszcze raz to samo
  4. twoja_funkcja();
  5. }
  6. }
ShadowD
Inaczej z bazą trochę:

|id|name|link|idRodzica|+

(Nie potrzebna Ci informacja o zagłębieni, przy ew. przeniesieniu zakładki będziesz zbędnie poprawiać te pola)

1. Pobierasz wszystkie dane
2. Wybierasz wszystkie z idRodzica==null
3. Wypisujesz je wraz z sprawdzeniem idRodzica== do aktualnej pozycji - tutaj skorzystaj z podpowiedzi @grzeee, czyli wypisując pole sprawdz czy ma dzieci, jeśli ma znów wypisuj tą samą funkcją.
4. Wykorzystując wszystkie dane = koniec

Całość będzie wypisywana w sposób pierwszy poziom i jego dzieci, dzieci dzieci i kolejna zakładka z idRodzica==0

Mam nadzieję, że rozumiesz. :-)

Możesz poczytać o drzewach - to temat o "układzie hierarchij w kodzie" czyli menu bez określonych poziomów, fora takiej jak to, 1 temat może mieć wiele tematów, a on zaś tematy i wątki.
lobopol
Struktura drzewiasta? http://blog.bexlab.pl/struktura-drzewiasta...nych-odc-1/366/
sliwa007
Próbowałem zrobić tak jak mówiłeś ale cos mi nie działa. Mógłbyś sprawdzić co może być nie tak ?

  1. function foo()
  2. {
  3. //pobieramy wszystkie
  4. $query = mysql_query("SELECT * FROM menu_poz WHERE parent_id = '0'");
  5. function boo() {
  6. //wyświetlamy wszystkie
  7. while($wynik = mysql_fetch_assoc($query)) {
  8. echo $wynik['name'].'<br>';
  9. //sprawdzamy czy ma dzieci
  10. $id = $wynik['id'];
  11. $query = mysql_query("SELECT * FROM menu_poz WHERE parent_id = '$id'");
  12. $row = mysql_num_rows($query);
  13. // jeśli ma dzieci powtarzaj funkcję
  14. if($row > 0 ) {
  15. boo();
  16. }
  17. }
  18. }
  19. }
  20. foo();
mortus
Jeśli to ma być funkcja rekurencyjna (bo tak się to nazywa), to powinna posiadać jakiś parametr/argument, którym w tym przypadku powinno być id_rodzica.
  1. function display_menu($parent_id = 0) {
  2. $sql1 = "SELECT `menu_poz`.`*` FROM `menu_poz` WHERE `parent_id` = {$parent_id}";
  3. $results1 = mysql_query($sql);
  4. echo '<ul>';
  5. while($row1 = mysql_fetch_assoc($results)) {
  6. echo '<li>';
  7. $sql2 = "SELECT COUNT(`id`) AS `liczba_dzieci` FROM `menu_poz` WHERE `parent_id` = {$row1['id']}";
  8. $results2 = mysql_query($sql2);
  9. $row2 = mysql_fetch_assoc($results2);
  10. if($row2['liczba_dzieci'] > 0) {
  11. display_menu($row1['id']);
  12. } else {
  13. echo $row1['nazwa'];
  14. }
  15. echo '</li>';
  16. }
  17. echo '</ul>';
  18. }


Oczywiście jest to najmniej optymalny sposób, który sprawdzi się w przypadku menu z niewielką liczbą podmenu. Natomiast sposobów na implementację drzewa kategorii jest co najmniej kilka, a powyższy jest najwolniejszym.
ShadowD
Niech się uczy od razu dobrej metody i nie zadawania stu zapytań do mysql..

Spróbuj wybrać dane z mysql i na nich operować nie tworząc kilku zapytań tylko jedno na początku.
sliwa007
znalazlem skrypt tworzący drzwo kategorii przez tylko jedno zapytanie, ale mam problem z wyświetlenim ich w poprawnje kolejności. Powiedzcie co robię źle.

  1. function getAll($query) {
  2. $res = mysql_query($query);
  3. $ret = array();
  4. if (!$res)
  5. return $ret;
  6. while ($r = mysql_fetch_assoc($res))
  7. $ret[] = $r;
  8. return $ret;
  9. }
  10.  
  11. function drzewoKategorii($kategorie = null, $rodzicId = 0, $zaglebienie = 0, $wynik = null)
  12. {
  13. if ($wynik == null)
  14. $wynik = array();
  15. if ($kategorie == null) {
  16. $query = "select * from menu_poz order by parent_id";
  17. $kategorie = getAll($query);
  18. }
  19. foreach ($kategorie as $kat) {
  20. if ($r["parent_id"] == $rodzicId) {
  21. $r["poziom"] = $zaglebienie;
  22. $wynik[] = $kat;
  23. $wynik = drzewoKategorii ($kategorie, $kat["id"], ($zaglebienie+1), $wynik);
  24. }
  25. }
  26. return $wynik;
  27. }
  28.  
  29. $drzewo = drzewoKategorii();
  30. foreach ($drzewo as $galaz) {
  31. for ($i=0; $i<=$galaz["parent_id"]; $i++) {
  32. echo '-';
  33. }
  34. echo $galaz["name"].'<br/>';
  35. }


Wynik wysiwetlany jest w ten sposób:
-Link 1
-Link 2
--Sub Link 1
--Sub Link 2
----trzeci rząd

a powinien być w ten sposób:
-Link 1
--Sub Link 1
----trzeci rząd
--Sub Link 2
-Link 2

Wiem że problem jest z sortowaniem po parent_id ale nie wiem jak to obejść. Skorzystałem ze skryptu na tej stronie. http://blog-programisty.pl/php/drzewo-kate...ja-rekurencyjna

lobopol
Zerknij w tego linka co podałęm i przeczytaj cały artykuł (ma kilka części) stronę mysql tam masz zrobioną praktycznie całą, a podpiąć pod to php to pikuś wystarczy chwilę pomyśleć.
sliwa007
Problem rozwiązany wywaliłem z kodu mortusa 2 zapytanie i wszystko chodzi cacy. Kod ma teraz tylko 1 zapytanie jest bardzo krótki:
  1. function display_menu($parent_id = 0) {
  2. $sql1 = "SELECT * FROM menu_poz WHERE parent_id = '$parent_id'";
  3. $results1 = mysql_query($sql1);
  4. echo '<ul>';
  5. while($row1 = mysql_fetch_assoc($results1)) {
  6. echo '<li>';
  7.  
  8. echo $row1['name'];
  9. display_menu($row1['id']);
  10.  
  11.  
  12. echo '</li>';
  13. }
  14. echo '</ul>';
  15. }
  16. display_menu();
mortus
Kod nie miał być krótszy, bo to nie o to chodzi. Jak dla mnie Twój kod teraz generuje puste listy <ul> </ul>. Nie miałeś się pozbywać zapytania, które wylicza liczbę dzieci, ale miałeś zrobić z tych dwóch zapytań jedno.
sliwa007
No jak, nie generuje pustych ul bo skrypt się wykonuje do póki nie wyczerpie się parent_id. tagi ul są w echo gdyby były generowane byłoby je widać w kodzie ? Dobrze myślę ?
ShadowD
Wiesz nie chcę nic mówić, ale Twój kod w cale nie wykonuje 1 zapytania, a tyle zapytań ile ma poziomów (wielokrotnie korzystasz z 1 zapytania). Kolega podał poradnik o drzewach, jest on całkiem ciekawy może warto by go przeczytać? Opisane jest tam (swoją drogą nawet w 2 sposobach) jak rozwiązać twój problem, mało tego są gotowe przykłady i zalety/wady danego rozwiązania.

sliwa007
Witam. Chyba rozwiązałem problem. Stworzyłem 2 funkcje jedna odpowiada za wyświetlenie nagłówka menu oraz za pobranie wszystkich danych z tablicy, natomiast druga za tworzenie menu. Czy to rozwiązanie jest ok ? Kod wygląda tak:

  1. function getAll($query) {
  2. $res = mysql_query($query);
  3. $ret = array();
  4. if (!$res)
  5. return $ret;
  6. while ($r = mysql_fetch_assoc($res))
  7. $ret[] = $r;
  8. return $ret;
  9. }
  10.  
  11. function display_menu($kategorie, $parent_id = 0) {
  12. $ile = count($kategorie);
  13. //wybieranie tych z id_parent = 0
  14. $i = 0;
  15. echo '<ul>';
  16. while($i < $ile) {
  17. if($kategorie[$i]['parent_id'] == $parent_id) {
  18. //czy ma dzieci
  19. $id = $kategorie[$i]['id'];
  20. echo '<li>'.$kategorie[$i]['name'].'</li>';
  21. $x = 0;
  22. while ($x < $ile) {
  23. if($kategorie[$x]['parent_id'] == $id) {
  24. echo '<ul>';
  25. echo '<li>'.$kategorie[$x]['name'].'</li>';
  26. $id1 = $kategorie[$x]['id'];
  27. display_menu($kategorie, $id1);
  28. echo '</ul>';
  29. }
  30. $x++;
  31. }
  32. }
  33. $i++;
  34. }
  35. echo '</ul>';
  36. }
  37.  
  38. function view_menu($menu) {
  39. //pobieranie wszystkich danych
  40. $query = mysql_query("SELECT * FROM menus WHERE name = '$menu'");
  41. $wynik = mysql_fetch_assoc($query);
  42. $menu = $wynik['name'];
  43. echo $wynik['desc'].'<br/>';
  44.  
  45. $query = "SELECT * FROM menu_poz WHERE menu = '$menu'";
  46. $kategorie = getAll($query);
  47. display_menu($kategorie);
  48. }
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.