Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [php][mysql] Wyświetlanie drzewka kategorii, problem przy duuuuzej ilosci kategorii i podkategorii
lectric
post
Post #1





Grupa: Zarejestrowani
Postów: 167
Pomógł: 1
Dołączył: 22.08.2006
Skąd: universe

Ostrzeżenie: (0%)
-----


Witam,

Otoz mam tabelke sql:

id | parent_id | name

Kategoria ktora posiada parent_id = 0 to kategoria glowna.

Napisalem dwie funkcje:

  1. <?php
  2. function drzewo($id){
  3.  
  4. global $tab,$glebokosc,$drzewko;
  5. $zapytanie="SELECT * FROM category WHERE parent_id='$id' ORDER BY name ASC";
  6. $wynik=mysql_query($zapytanie);
  7.  
  8. while($wiersz=mysql_fetch_assoc($wynik)) {
  9. $drzewko[]=array('id'=>$wiersz[id],'nazwa'=>$wiersz[name],'glebokosc'=>(int)$glebokosc);
  10.  
  11. $zapytanie2="SELECT * FROM category WHERE parent_id=".$wiersz[id]." ORDER BY name ASC";
  12. $wynik2=mysql_query($zapytanie2);
  13. if(mysql_num_rows($wynik2)>0) {
  14. $glebokosc++;
  15. drzewo($wiersz[id]);
  16. $glebokosc--;
  17. }
  18. }
  19. }
  20.  
  21. function rysuj($ilosc,$nazwa,$id) {
  22.  
  23. if($ilosc == 0 ) {
  24. echo "<option value='$id' style='color:#0086df;'>".$nazwa."</option><br>";
  25.  
  26. }
  27. else {
  28. $licznik = 0;
  29. while($licznik <= $ilosc-1) 
  30. {
  31. $kreska= $kreska." &nbsp;&nbsp;&nbsp;|";
  32. $licznik++;
  33. }
  34. echo "<option value='$id'>".$kreska."__".$nazwa."</option>";
  35. }
  36. }
  37. ?>


wywołanie:

  1. <?php
  2. drzewo(0);
  3. foreach ($drzewko as $tab) 
  4. echo rysuj_zaznaczone($tab[glebokosc],$tab[nazwa],$tab[id],$kat_glowna);
  5. ?>



Gdy testowalem to na kilkunastu kategoriach wszystko bylo ok ale gdy docelowo uzylem okolo 10 tys. kategorii pojawil sie problem...
Testujac to na localhost po chwili wszystko zaczelo sie wieszac.
Prosze Was o pomoc.


--------------------
Potrzebujesz dodać darmowe ogłoszenia ?, w takim razie musisz odwiedzić to miejsce !
Presell - tutaj dodasz swoj artykul za darmo ! Presell Page dla wszystkich bez limitów i utrudnień
Masz firme ? Ta baza firm jest dla Ciebie i Twoich znajomych są też śmieszne filmiki
Go to the top of the page
+Quote Post
qqrq
post
Post #2





Grupa: Zarejestrowani
Postów: 418
Pomógł: 8
Dołączył: 16.11.2006

Ostrzeżenie: (0%)
-----


No nic dziwnego, że się zapchało - 10000 to ździebko dużo... smile.gif

Inna sprawa, że popatrz sobie ile to zapytań będzie przy takiej ilości kategorii. Najlepiej wszystkie kategorie pobierz od razu, jednym zapytaniem, a potem na tym co otrzymasz manipuluj po swojemu. Posortuj od razu (w zapytaniu) po parent_id - tak chyba będzie łatwiej to potem ogarnąć...

Ten post edytował qqrq 5.09.2007, 12:32:46


--------------------
Go to the top of the page
+Quote Post
phpion
post
Post #3





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Problem leży zapewne w tym, że dla każdej kategorii sprawdzasz czy posiada podkategorie za pomocą zapytania SQL wykonywanego w pętli. Nie dziw się, że przy tak dużej liczbie pętli skrypt pada. Możesz to zrobić bez problemu na 1 zapytaniu!
  1. SELECT * FROM kategorie

Za pomocą tego zapytania budujesz sobie drzewko postaci:
  1. <?php
  2. $cat[0] = array(
  3. 1 => 'Kategoria1',
  4. 2 => 'Kategoria2'
  5. );
  6. $cat[1] = array(
  7. 3 => 'Kategoria11',
  8. 4 => 'Kategoria12'
  9. );
  10. $cat[4] = array(
  11. 5 => 'Kategoria121'
  12. );
  13. ?>

czyli index tablicy $cat to kategoria nadrzędna. Każdy element $cat jest również tablicą zawierającą podkategorie. Wystarczy teraz zwykłą pętlą przelatywać tablicę $cat w poszukiwaniu kategorii i podkategorii. Równocześnie, żeby zaoszczędzić czas, możesz po zbudowaniu odpowedniej gałęzi usuwać z tablicy użyte dane aby przy następnym przebiegu pętli nie sprawdzać tych, które zostały wcześniej użyte.
Go to the top of the page
+Quote Post
athabus
post
Post #4





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Możesz też zrobić coś innego... Zdaje się że gdzieś jest nawet artykuł o tym na wortalu. Id może mieć postać np. liczby 10 cyfrowej gdzie pierwsze 2 cyfry to id kategorii glownej, dwie kolejne to id podkategorii itd.

np.

1000000000 - kategoria glowna
1001000000 - podkakategoria
1002000000 - inna podkategoria
1002010000 - podakategoria poprzedniej podkategorii,
2000000000 - inna kategoria główna itd

W czymś takim sortowanie i wybieranie zagnieżdżonych pozycji jest znacznie łatwiejsze. Z drugiej strony struktura jest trochę mniej skalowalna, ale jeśli masz konkretny przypadek, to zapewne sam określisz wady i zalety takiego rozwiązania.
Go to the top of the page
+Quote Post
Ludvik
post
Post #5





Grupa: Przyjaciele php.pl
Postów: 698
Pomógł: 3
Dołączył: 28.03.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


phpion.com: Pobranie wszystkich elementów z tej tablicy (10 tys. rekordów) skutecznie zawali pamięć... W ten sposób wszystko można zrobić na jednym zapytaniu, tylko trzeba się potem namęczyć, żeby zapisać wszystkie warunki w postaci kodu (niekoniecznie efektywnego).

Można zastosować nested sets, ale wstawianie i przenoszenie elementów wymaga aktualizacji sporej części rekordów (mimo tego, że nie są to skomplikowane operacje, zwykle 2 zapytania starczają). Pobranie wszystkich elementów podrzędnych jest bardzo proste i wymaga tylko jednego zapytania... Ale tak jak mówiłem, utrzymanie nested sets na takiej dużej bazie nie musi być przyjemne (nie testowałem osobiście...). Na Twoim miejscu przestudiowałbym dokładniej temat drzewek (sam się nad tym męczę)...


--------------------
Go to the top of the page
+Quote Post
phpion
post
Post #6





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(Ludvik @ 5.09.2007, 14:55:30 ) *
phpion.com: Pobranie wszystkich elementów z tej tablicy (10 tys. rekordów) skutecznie zawali pamięć...

Racja, ale kto normalny robi tyle kategorii biggrin.gif hehe, poza tym przecież dane można cache'ować co rozwiąże problem. Wystarczy to zrobić z głową. W moim przykładzie nie jest problemem pobranie ścieżki od aktualnej kategorii do korzenia, nie ma problemu z pobraniem samych id kategorii potomnych itd itd. Wszystko odbywa się już na tablicach.
Go to the top of the page
+Quote Post
lectric
post
Post #7





Grupa: Zarejestrowani
Postów: 167
Pomógł: 1
Dołączył: 22.08.2006
Skąd: universe

Ostrzeżenie: (0%)
-----


Nie moge używać metody zagnieżdżenia kategorii , musze pozostac przy pierwotnej (rodzic, dziecko)


--------------------
Potrzebujesz dodać darmowe ogłoszenia ?, w takim razie musisz odwiedzić to miejsce !
Presell - tutaj dodasz swoj artykul za darmo ! Presell Page dla wszystkich bez limitów i utrudnień
Masz firme ? Ta baza firm jest dla Ciebie i Twoich znajomych są też śmieszne filmiki
Go to the top of the page
+Quote Post
Ludvik
post
Post #8





Grupa: Przyjaciele php.pl
Postów: 698
Pomógł: 3
Dołączył: 28.03.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Przy pobieraniu n poziomów możesz pobrać wszystkie dane za pomocą n zapytań, jeżeli dobrze myślę... Pomyśl coś w tym kierunku (pisane z palca, nie testowane, nie gwarantuję poprawnego działania tongue.gif ).

  1. <?php
  2. function drzewo($id, $glebokosc){
  3. $zapytanie = "SELECT * FROM category WHERE parent_id=$id ORDER BY name ASC";
  4. $wynik = mysql_query($zapytanie);
  5.  
  6. $rodzice = array();
  7.  
  8. while ($wiersz = mysql_fetch_array($wynik)) {
  9. $rodzice[] = $wiersz['id'];
  10. $drzewko[] = array('id' => $wiersz[id], 'nazwa' => $wiersz[name],
  11. 'glebokosc' => 0);
  12. }
  13.  
  14. for ($i = 1; $i < $glebokosc; $i++) {
  15.  $rodzice = implode(', ', $rodzice);
  16. $zapytanie = "SELECT * FROM category WHERE parent_id IN (" . $rodzice
  17. . ") ORDER BY name ASC";
  18. $wynik = mysql_query($zapytanie2);
  19. $rodzice = array();
  20. while ($wiersz = mysql_fetch_array($wynik)) {
  21. $rodzice[] = $wiersz['id'];
  22. $drzewko[] = array('id' => $wiersz[id], 'nazwa' => $wiersz[name],
  23. 'glebokosc' => (int)$glebokosc);
  24. }
  25. }  
  26.  
  27. return $drzewko;  
  28. }
  29. ?>


Ten post edytował Ludvik 5.09.2007, 18:10:32


--------------------
Go to the top of the page
+Quote Post
lectric
post
Post #9





Grupa: Zarejestrowani
Postów: 167
Pomógł: 1
Dołączył: 22.08.2006
Skąd: universe

Ostrzeżenie: (0%)
-----


Dzieki.
Tylko, ze przy tej metodzie jest utracony wazny element, ktora kategoria dziecko jest pod ktora kategoria rodzicem.


--------------------
Potrzebujesz dodać darmowe ogłoszenia ?, w takim razie musisz odwiedzić to miejsce !
Presell - tutaj dodasz swoj artykul za darmo ! Presell Page dla wszystkich bez limitów i utrudnień
Masz firme ? Ta baza firm jest dla Ciebie i Twoich znajomych są też śmieszne filmiki
Go to the top of the page
+Quote Post
Ludvik
post
Post #10





Grupa: Przyjaciele php.pl
Postów: 698
Pomógł: 3
Dołączył: 28.03.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Ale przecież masz pole parent_id w bazie, więc czemu go nie użyć do odwzorowania związków? Dopisanie tego nie będzie raczej problemem...


--------------------
Go to the top of the page
+Quote Post
crashu
post
Post #11





Grupa: Zarejestrowani
Postów: 6
Pomógł: 0
Dołączył: 14.04.2007

Ostrzeżenie: (0%)
-----


kiedys niepotrzebnie rozwiazlem ten problem

  1. <?php
  2. $db['query'] = 'SELECT * FROM '.CATEGORY_TABLE.' WHERE blog = '.$iBlogID.' ORDER BY sub ASC';
  3. $db->query();
  4. $db->num_rows();
  5.  
  6. if( $db['rows'] < 1 ) return;
  7.  
  8. $kubel = array();
  9. $tree = array();
  10. //Tutaj tworze drzewo
  11. while( $row = $db->fetch_array() ) {
  12.  
  13. $id = $row['id'];
  14.  
  15. $kubel[$id]['id'] = $id;
  16. $kubel[$id]['name'] = $row['name'];
  17. $kubel[$id]['subid'] = $row['sub'];
  18.  
  19. if( !is_array($kubel[$id]['subs']) ) $kubel[$id]['subs'] = array();
  20.  
  21. if( $row['sub'] == 0 ) {
  22.  
  23. array_push($tree, &$kubel[$id]);
  24. }
  25. else {
  26.  
  27. if( !is_array($kubel[$row['sub']]['subs']) )
  28. $kubel[$row['sub']]['subs'] = array();
  29.  
  30. array_push($kubel[$row['sub']]['subs'], &$kubel[$id]);
  31. }
  32. }
  33.  
  34. //zaczynam rysowac
  35. if( count($tree) < 1 ) return '<categories/>';
  36.  
  37. $Stos = array();
  38. $string = '';
  39. reset($tree);
  40.  
  41. $row = @current($tree);
  42.  
  43. while( 1 ) {
  44.  
  45. if( $row == null ) {
  46.  
  47. if( count($Stos) > 1 ) {
  48.  
  49. array_pop($Stos);
  50. $last = array_pop($Stos);
  51. $row = @next($last['subs']);
  52. array_push($Stos, $last);
  53.  
  54. $string .= '</category>'.NL;
  55. if( $row == null ) continue;
  56. }
  57. else if( count($Stos) == 1 ) {
  58.  
  59. $row = array_pop($Stos);
  60. if( count($row['subs']) > 0 )
  61. $string .= '</category>'.NL;
  62.  
  63. $row = null;
  64. if( $row == null ) continue;
  65. }
  66. else {
  67.  
  68. $row = @next($tree);
  69. @reset($row);
  70. if( $row == null ) break;
  71. }
  72. }
  73.  
  74. if( count($row['subs']) > 0 ) {
  75.  
  76. $string .= '<category name="'.$row['name'].'" id="'.$row['id'].'" >'.NL;
  77.  
  78. reset($row['subs']);
  79. array_push($Stos, $row);
  80. $row = current($row['subs']);
  81. continue;
  82. }
  83. else {
  84.  
  85. $string .= '<category name="'.$row['name'].'" id="'.$row['id'].'" />'.NL;
  86.  
  87. if( count($Stos) > 0 ) {
  88.  
  89. $last = array_pop($Stos);
  90. $row = @next($last['subs']);
  91. array_push($Stos, $last);
  92. }
  93. else $row = null;
  94. }
  95. }
  96.  
  97. unset($tree);
  98. unset($kubel);
  99. unset($Stos);
  100.  
  101. echo '<categories>'.NL.$string.NL.'</categories>';
  102. ?>


--------------------
Black Tarantula
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 19.08.2025 - 01:53