Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Iteratory - jak działa ta klasa ?
Forum PHP.pl > Forum > Przedszkole
fiasko
  1. class QueryIterator implements Iterator
  2. {
  3. private $result;
  4. private $connection;
  5. private $data;
  6. private $key=0;
  7. private $valid;
  8. function __construct($dbname, $user, $password)
  9. {
  10. $this->connection = pg_connect("host=localhost port=5432 dbname={$dbname} user={$user} password={$password}");
  11. }
  12. public function exceute($query)
  13. {
  14. $this->result = pg_query($this->connection,$query);
  15. if (pg_num_rows($this->result)>0)
  16. $this->next();
  17. }
  18. public function rewind() {}
  19. public function current()
  20. {
  21. return $this->data;
  22. }
  23. public function key()
  24. {
  25. return $this->key;
  26. }
  27. public function next()
  28. {
  29. if ($this->data = pg_fetch_assoc($this->result))
  30. {
  31. $this->valid = true;
  32. $this->key+=1;
  33. }
  34. else
  35. $this->valid = false;
  36. }
  37. public function valid()
  38. {
  39. return $this->valid;
  40. }
  41. }
  42.  
  43.  
  44.  
  45. $qi = new QueryIterator("moja_baza", "use5454" , "65454544444");
  46. $qi -> exceute("select name, email from users");
  47. while ($qi -> valid())
  48. {
  49. echo "<pre>";
  50. print_r($qi -> current());
  51. echo "</pre>";
  52. $qi -> next();
  53. }


Staram się zrozumieć działanie tej klasy. Ale nie do końca wiem co się dzieje .

Zacznę więc od początku :

W utworzonej instancji klasy QueryIterator wywołujemy metodę konstruktora i łączymy się z bazą postgresql.
Następnie wywołujemy metodę exceute w której tworzymy zapytanie do bazy danych na podstawie utworzonego identyfikatora połączenia właściwości connection i zaptyania query. Następnie przypisujemy wynik do właściwości result. Następnie sprawdzamy czy zapytanie zwróciło nam co najmniej jeden wiersz i jeśli tak to wywołujemy kolejna metodę next().

Tu tez nie rozumiem dlaczego ona musi nazwać się next() skoro to nazwa metody ? Z tego co mi się wydaje w definicji metody next(); jej dziłanie jest następujące.
z wyniku zapytania czyli z właściwości result tworozna jest tablica asocjacyjna, która zwraca wynik do właściwości data. Właściwość valid w przypadku pozytywnego zwrócenia wyniku otrzymuje wartość true, a właściwość key zwiększa swoją wartość klucza z 0 o jeden z każdym wywołaniem metody next . Oczywiście wartość false dla właściwości valid wystąpi gdy wywołanie metody nastąpi gdy pg_fetch_assoc nie zwróci wyniku.

No a co dalej to już nie mam pojęcia.

Bo nie wiem co się dzieje i jak są wywoływane metody
public function rewind() {}
public function current()



Proszę o jakieś wytłumaczenie jak działa ta klasa. Niestety autor książki nie opisał, dokładnie sposobu działania klas i tak muszę sam dociekać co i jak .

Dlatego proszę o napisanie co się dzieje dalej.

wookieb
Czy MANUAL gryzie?? http://php.net/iterator
fiasko
Nie gryzie - ale czy manual wyczerpuje te zagadnienie ? Wątpię. Dlatego dałem konkretny przykład klasy. Chcę zrozumieć jak to działa.

No i wymiękli smile.gif

Ech tam - doszedłem do tego , że metody key(), next() ,current(), rewind() są abstakcyjne i muszą porostu być zdefiniowane nawet gdy nic nie robią.

Nie wiem też co za różnicę robi $this->key+=1; bo za komentowanie tej linii powoduje dalej poprawne działanie klasy.

Nadal nie rozumiem jednak w jaki sposób current() wie, że wywołałem metodę next() na tej tablicy $data i że zwiększyłem dla na niej wskaźnik.


Jak to jest przekazywane ?


Normalnie działa to tak :

  1.  
  2. <?php
  3. $transport = array('stopy', 'rower', 'samochód', 'samolot');
  4. $tryb = current($transport); // $tryb = 'stopy';
  5. $tryb = next($transport); // $tryb = 'rower';
  6. $tryb = current($transport); // $tryb = 'rower';
  7. $tryb = prev($transport); // $tryb = 'stopy';
  8. $tryb = end($transport); // $tryb = 'samolot';
  9. $tryb = current($transport); // $tryb = 'samolot';
  10. echo $tryb;
  11. ?>


Czy wobec tego Iterator przechodzi przez wszystkie tablice w obiekcie ?
mortus
Zaprezentowana klasa QueryIterator pozwala na sekwencyjne (jeden po drugim) przejrzenie wyników dowolnego zapytania do bazy danych PostgreSQL. Nie realizuje ona jednak wszystkich możliwości Iteratora np. ze względu na to, że wyniki mogą być przeglądane tylko do przodu, nie można ich przejrzeć ponownie, ani też wrócić do poprzedniego.

Cytat
Nie wiem też co za różnicę robi $this->key+=1; bo za komentowanie tej linii powoduje dalej poprawne działanie klasy.

Akurat w przedstawionej klasie key (klucz, index) nie jest wykorzystywany. Natomiast key() pobiera indeks elementu tablicy, który aktualnie przeglądamy.

Cytat
Nadal nie rozumiem jednak w jaki sposób current() wie, że wywołałem metodę next() na tej tablicy $data i że zwiększyłem dla na niej wskaźnik.

Metoda current() wcale nie wie, że wywołałeś metodę next(). Zauważ tylko, że zarówno current() jak i next() operują na tej samej zmiennej $this->data, przy czym current() pobiera wartość tej zmiennej, a next() tę wartość nadpisuje.

Natomiast metoda rewind() (pol. przewiń) powinna przywrócić nam stan początkowy, ale tutaj również nie jest wykorzystywana.
fiasko
No ale przecież metoda next() nie operuje bezpośrednio na tej tablicy bo nie ma żadnego akcesora dostępu do właściwości $data. Równie dobrze mogę jej nie używać i np zadeklarować tą podobną metodę tak :

  1. public function next_step() {
  2. echo "next<br>";
  3. if ($this->data = pg_fetch_assoc($this->result))
  4. {
  5. $this->valid = true;
  6. //$this->key+=1;
  7. echo "klucz" . $this -> key."<br>";
  8. }
  9. else {
  10. $this->valid = false;}
  11. echo $this->valid;
  12. }


Efekt będzie taki, że z każdym wywołaniem tej metody indeks zwiększy się o jeden. - sprawdziłem

Doszedłem do wniosku, że poprawnie i sensownie wykorzystywana jest w przykładzie tej klasy tylko pokryta metoda current() dla klasy abstrakcyjnej, która potrafi odczytać bieżący wskaźnik . Troszkę autor książki chyba nie wiedział jak sensownie przedstawić działanie tej klasy. Generalnie nie polecam książki programowanie obiektowe w PHP5 Hasin Hayder ze względu na ilość błędów w kodzie oraz zupełnie nie trafione przykłady. Zero tłumaczenia co, jak, lub dlaczego.

  1. <?
  2. <?
  3. class QueryIterator implements Iterator
  4. {
  5. private $result;
  6. private $connection;
  7. private $data;
  8. private $key=0;
  9. private $valid;
  10. function __construct($dbname, $user, $password)
  11. {
  12. $this->connection = pg_connect("host=localhost port=5432 dbname={$dbname} user={$user} password={$password}");
  13. }
  14. public function exceute($query)
  15. {
  16. $this->result = pg_query($this->connection,$query);
  17. if (pg_num_rows($this->result)>0)
  18.  
  19. $this-> next_step();
  20.  
  21. }
  22. public function rewind() {
  23.  
  24. }
  25. public function current()
  26. {
  27.  
  28. return $this->data;
  29. }
  30.  
  31. public function key()
  32. {
  33.  
  34. }
  35.  
  36. public function next()
  37. {
  38.  
  39. }
  40. public function next_step() {
  41.  
  42. if ($this->data = pg_fetch_assoc($this->result))
  43. {
  44. $this->valid = true;
  45. }
  46. else {
  47. $this->valid = false;}
  48. }
  49.  
  50. public function valid()
  51. {
  52. return $this->valid;
  53. }
  54.  
  55. }
  56.  
  57.  
  58.  
  59. $qi = new QueryIterator("moja_baza", "usr_" , "65545421");
  60. $qi -> exceute("select name, email from users");
  61.  
  62.  
  63.  
  64. while ($qi -> valid())
  65. {
  66. echo "<pre>";
  67. print_r($qi -> current());
  68. echo "</pre>";
  69. $qi -> next_step();
  70. }
  71.  
  72.  
  73.  
  74. ?>
  75.  
mortus
Cytat(fiasko @ 16.08.2011, 13:39:20 ) *
No ale przecież metoda next() nie operuje bezpośrednio na tej tablicy bo nie ma żadnego akcesora dostępu do właściwości $data.

Jak to nie?
  1. if($this->data = pg_fetch_assoc($this->result))

Przecież to jest przypisanie zmiennej $this->data wiersza wyciągniętego z $this->result. Jeśli nie ma więcej wyników, to pg_fetch_assoc() zwraca false.
Metoda next() również spełnia swoją rolę (przynajmniej po części).

Natomiast sama klasa QueryIterator, nie do końca wykorzystuje wszystkie możliwości Iteratora, jak już wcześniej pisałem.

Teraz jeszcze uświadomiłem sobie, że i metodę key() możemy symbolicznie wykorzystać, bo wskazuje ona numer aktualnego rekordu spośród wszystkich zwróconych.
fiasko
No to jeszcze pozostaje mi zapytać czy waszym zdaniem taki przykład powinien znaleźć się w książce do programowania obiektowego aby pokazać jak działają Iteratory ?
Tą klasę już rozgryzłem.



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.