Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: PHP i mysql vadem. - problem z przykładem w książce
Forum PHP.pl > Forum > PHP > Object-oriented programming
GreeN_DG
Witam serdecznie. Jak czytałem na kilku forach książka (php i mysql. tworzenie stron www. vademecum profesjonalisty. wydanie czwarte) posiada trochę błędów i nie należy ponoć do wybitnych. Chodzi mi o pewien przykład z rozdziału 31 - "tworzenie forum www". Wydaje mi się, iż pomóc mogą mi osoby, które posiadają tą książkę. Jest tam klasa, która ma służyć do budowy drzewa artykułów tegoż forum. To nie cały listing tej klasy, ale wystarczy do objaśnienia problemu :

  1. // funkcje służące do pobierania, tworzenia i wyświetlania drzewa
  2. // znajdują się w tym pliku
  3.  
  4. class wezel_drzewa
  5. {
  6. // każdy węzeł drzewa posiada zmienne składowe zawierające wszystkie dane
  7. // artykułu poza jego właściwym tekstem
  8. public $c_id_artykulu;
  9. public $c_tytul;
  10. public $c_umieszczajacy;
  11. public $c_umieszczony;
  12. public $c_potomek;
  13. public $c_lista_pot;
  14. public $c_glebokosc;
  15.  
  16. public function __construct($id_artykulu, $tytul, $umieszczajacy, $umieszczony, $potomek,
  17. $rozwin, $glebokosc, $rozwiniety, $podlista)
  18. {
  19. // konstruktor konfiguruje zmienne członkowskie, oraz, co ważniejsze,
  20. // rekurencyjnie tworzy niższe części drzewa
  21. $this->c_id_artykulu = $id_artykulu;
  22. $this->c_tytul = $tytul;
  23. $this->c_umieszczajacy = $umieszczajacy;
  24. $this->c_umieszczony = $umieszczony;
  25. $this->c_potomek =$potomek;
  26. $this->c_lista_pot = array();
  27. $this->c_glebokosc = $glebokosc;
  28.  
  29. // co jest pod tym węzłem ważne jest tylko jeżeli posiada potomków i jest
  30. // zaznaczony do rozwinięcia
  31. // podlisty są zawsze rozwinięte
  32. if(($podlista||$rozwin) && $potomek)
  33. {
  34. $lacz = lacz_bd();
  35.  
  36. $zapytanie = "select * from naglowek where przodek = $id_artykulu order by umieszczony";
  37. $wynik = $lacz->query($zapytanie);
  38.  
  39. for ($licznik=0; $rzad = @$wynik->fetch_assoc(); $licznik++)
  40. {
  41. if($podlista||$rozwiniety[ $rzad['id_artykulu'] ] == true)
  42. $rozwin = true;
  43. else
  44. $rozwin = false;
  45. $this->c_lista_pot[$licznik]= new wezel_drzewa($rzad['id_artykulu'],$rzad['tytul'],
  46. $rzad['umieszczajacy'],$rzad['umieszczony'],
  47. $rzad['potomek'], $rozwin,
  48. $glebokosc+1, $rozwiniety, $podlista);
  49. }
  50. }
  51. }


A to listing gdzie tworzony jest egzemplarz tej klasy :

  1. function wyswietl_drzewo($rozwiniety, $wiersz = 0, $start = 0)
  2. {
  3. // wyświetlenie widoku drzewka konwersacji
  4.  
  5. global $szerokosc_tabeli;
  6. echo "<table width = '$szerokosc_tabeli'>";
  7.  
  8. // sprawdzenie, czy wyświetlana jest pełna lista czy podlista
  9. if($start>0)
  10. $podlista = true;
  11. else
  12. $podlista = false;
  13.  
  14. // konstrukcja struktury drzewa przedstawiającej podsumowanie konwersacji
  15. $drzewo = new wezel_drzewa($start, '', '', '', 1, true, -1, $rozwiniety, $podlista);
  16.  
  17. // powiedz drzewu żeby samo się wyświetliło
  18. $drzewo->wyswietl($wiersz, $podlista);
  19.  
  20. echo '</table>';
  21. }


Więc od początku. Gdy tworzony jest egzemplarz tej klasy,funkcja konstrukcyjna sprawdza czy dany artykuł posiada dzieci, następnie tworzony jest nowy egzemplarz tej klasy przez co funkcja konstrukcyjna znów.... i tak dalej i tak dalej...

Chodzi mi głownie o tą część :

  1. $this->c_lista_pot[$licznik]= new wezel_drzewa($rzad['id_artykulu'],$rzad['tytul'],
  2. $rzad['umieszczajacy'],$rzad['umieszczony'],
  3. $rzad['potomek'], $rozwin,
  4. $glebokosc+1, $rozwiniety, $podlista);


Dajmy na to że mamy dwa artykuły A i B na poziomie "0". Następnie dwa artykuły C i D gdzie C jest dzieckiem A i D jest dzieckiem C. Czyli A->C->D i B obok A. Gdy tworzony jest pierwszy egzemplarz klasy konstruktor sprawdza w badzie że są dwa artykuły na "0" poziomie ( A i B ) . Pobiera ich dane. Następnie w bloku iteracyjnym tworzony jest nowy egzemplarz (który jest tablicą) omawianej klasy : c_lista_pot[0] i tam następuje znów wywołanie konstruktora, potem iteracja i znów tworzony jest egzemplarz omawianej klasy: c_lista_pot[0]. Więc co mamy dwa egzemplarze c_lista_pot[0] ? Chyba że ja czegoś nie rozumiem. Przecież jak będzie kilka gałęzi to każdy pierwszy element będzie c_lista_pot[0] bo indeks pochodzi od funkcji iteracyjnej.. To samo tyczy się zmiennej $glebokosc+1. Przecież gdy kończy analizowanie danej gałęzi i wraca do góry drzewa aby analizować kolejną gałąź to musi ta zmienna się zerować aby głębokość pierwszego elementu tej gałezi była 0. Mam nadzieję, że nie zamieszałem zbytnio, i faktem jest jak już pisałem wcześniej, że najlepiej jeśli ktoś posiada tą książkę aby mi pomóc. W razie czego mogę więcej napisać informacji z książki.

Pozdrawiam
GreeN
Zyx
To jest normalna rekurencja i wydaje mi się po tym, co napisałeś, że zupełnie jej nie rozumiesz. Każde wywołanie funkcji/metody posiada własny zestaw zmiennych i osobny wpis na stosie wywołań. Jeśli wywołanie nr 5 sobie zmienia wartość jakiejś zmiennej, to ta zmiana jest widoczna wyłącznie w tym wywołaniu i nie wpływa na działanie innych funkcji. Tak samo jest z $c_lista_pot - każdy obiekt ma własną listę.

Już tak na marginesie... jeśli tak wyglądają przykłady w tej książce, to weź Ty sobie lepiej zmień źródło, z którego się uczysz. Nie wywołuje się rekurencyjnie zapytań SQL! To jest przecież wzorcowa wręcz metoda zajechania bazy danych. Liczba zapytań, jakie dane żądanie HTTP może wysłać do bazy danych, powinna być ograniczona z góry jakąś stałą wartością na zasadzie "ta akcja może wysłać 4, 5 lub 6 zapytań w zależności od jakichś ustawień, ale nigdy więcej".
GreeN_DG
Czy jesteś mi w stanie to dokładniej wytłumaczyć? Czyli mogą istnieć obiekty o tych samych nazwach? No bo tak to zrozumiałem, bo każda gałąź główna staje się tablicą i te tablice mają te same nazwy. Te tablice, które wyrażają daną gałąź drzewa układają się na stosie? Czy mógłbyś podać sensowne publikacje które mogą przybliżyć mi programowanie obiektowe?
Zyx
Nie ma czegoś takiego, jak "nazwa obiektu". Jest nazwa klasy, a klasa to coś zupełnie innego, niż obiekt. Może istnieć co najwyżej jedna klasa o nazwie X, może istnieć dowolna liczba obiektów klasy X.

http://pl.wikibooks.org/wiki/PHP/Czym_jest...ie_obiektowe%3F
GreeN_DG
Dziękuje za odpowiedź. Czyli jeśli dobrze rozumiem w tym momencie :

c_lista_pot[$licznik]= new wezel_drzewa.....

tworzony jest za każdym razem nowy obiekt klasy "wezel_drzewa" który jako indywiduum może posiadać własne właściwości (pola) (nie ważne że to będzie kilka razy c_lista_pot[0]) i każdy ten obiekt kolejno odkładany jest na stos? Jedynym sposobem potem w kolejnej funkcji dostania się do danego obiektu jest zdejmowanie po kolei obiektów ze stosu aż dojdziemy do pożądanego? Bo takim czymś :

$this->c_lista_pot[]->Coś tam... wskażemy na pierwszy obiekt leżący na stosie?
Zyx
Tak, każdy obiekt ma własne wartości wszystkich atrybutów, niezależne od innych obiektów tej samej klasy. Zatem też każdy obiekt reprezentujący artykuł posiada swoją własną listę potomków. Natomiast tu jeszcze taka uwaga: $c_lista_pot to lista, a nie żaden stos. Poczytaj sobie, czym jest jedno, a czym drugie w informatyce, ponieważ mylisz pojęcia.
GreeN_DG
Nie rozumiem pewnej kwestii. Mając daną klasę "jedzenie" to czy :

$chleb = new jedzenie();
$chleb = new jedzenie();
$chleb = new jedzenie();

tworzone są trzy obiekty klasy jedzenie?

bo w tamtym przykładzie jeśli założymy że jest znaczna ilość artykułów, wiele gałęzi to taki przypadek :

c_lista_pot[0]= new wezel_drzewa.....

powtórzy się wiele razy.


-------------------------------------------------
edit.

Widzę że cicho w temacie. Wydaje mi się że jeśli ma to być lista artykułów to powinno być zamiast tak

  1. $this->c_lista_pot[$licznik]= new wezel_drzewa....


tak

  1. $this->c_lista_pot[id artykulu]= new wezel_drzewa....


Wtedy utworzy się lista gdzie dany rekord tablicy będzie wskazywał na dany obiekt (artykuł).

-----------------
edit2

Napisałem bzdurę bowiem przecież nie jest powiedziane iż np. dziecko artykułu o id=2 będzie miało id=3. Zanim pojawi się odpowiedź na id=2 może pojawić się wiele nie związanych z nim artykułów. W tym wypadku przy kodzie co podałem wyżej powstanie lista artykułów o złej kolejności. Wynika z tego, że poprostu powinno być :

<php>$this->c_lista_pot[kolejny rekord tablicy]= new wezel_drzewa...</php>
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.