Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [OOP] Dostęp do danych parametru w klasie - dyskusja
Forum PHP.pl > Forum > PHP > Object-oriented programming
Athlan
W tytule tematu napisałem "dyskusja". Dziś nie przychodzę na forum z pyaniem, ale z prośbą o wyrązenie swoich opinii na możliwości jakie daje nam OOP.

Przypuśćmy, że mamy do napisania klasę, która będzie importować dane w formie tablicy i je udostępniać (rzucam przykładem, aby zobrazowac jakie możliwości daje OOP).

Przypadek nr 1:

  1. <?php
  2. final class MyConfigObject
  3. {
  4. private $_aParametrs = array();
  5.  
  6. public function __construct(array $aFields = array())
  7. {
  8. $this->_aParametrs = $aFields;
  9. }
  10.  
  11. public function __get($sParam)
  12. {
  13. if(!isset($this->_aParametrs[$sParam]))
  14. return null;
  15.  
  16. if(is_array($this->_aParametrs[$sParam]))
  17. return new MyConfigObject($this->_aParametrs[$sParam]);
  18. else
  19. return $this->_aParametrs[$sParam];
  20. }
  21.  
  22. public function __set($sParam, $mValue)
  23. {
  24. return $this->_aParametrs[$sParam] = $mValue;
  25. }
  26. }
  27. ?>


Użycie przypadka 1:

  1. <?php
  2. $aSampleArray = array(
  3. 'field1' => 'value1',
  4. 'field2' => array('fieldarray1' => 'valuearray1'),
  5. 'field3' => array('fieldarray2' => array('fieldarray3' => array('fieldarray4' => 'valuearray4'))),
  6. );
  7.  
  8. $oMyConfig = new MyConfigObject($aSampleArray);
  9.  
  10. echo $oMyConfig->field1; // value1
  11. echo $oMyConfig->field2->fieldarray1; // valuearray1
  12. echo $oMyConfig->field3->fieldarray2->fieldarray3->fieldarray4 // valuearray4
  13. ?>


Plusy:
  • traktujemy elementy tablicy jako obiekty, co jest zgodne z teorią OOP
  • banalny wręcz dostęp do danych
Minusy:
  • nie ma możliwości wykonania operacji for(), foreach() na elementach tablicy (jest obiektem)
Przykład numer 2:

  1. <?php
  2. final class MyConfigArray implements ArrayAccess
  3. {
  4. private $_aParametrs = array();
  5.  
  6. public function __construct(array $aFields = array())
  7. {
  8. $this->_aParametrs = $aFields;
  9. }
  10.  
  11. public function offsetGet($sParam)
  12. {
  13. if(!isset($this->_aParametrs[$sParam]))
  14. return null;
  15.  
  16. if(is_array($this->_aParametrs[$sParam]))
  17. return new MyConfigArray($this->_aParametrs[$sParam]);
  18. else
  19. return $this->_aParametrs[$sParam];
  20. }
  21.  
  22. public function offsetSet($sParam, $mValue)
  23. {
  24. return $this->_aParametrs[$sParam] = $mValue;
  25. }
  26.  
  27. public function offsetExists($sParam)
  28. {
  29. return (isset($this->_aParametrs[$sParam]) ? true : false);
  30. }
  31.  
  32. public function offsetUnset($sParam)
  33. {
  34. unset($this->_aParametrs[$sParam]);
  35. }
  36. }
  37. ?>


Przykład uzycia sposobu nr 2:
  1. <?php
  2. $aSampleArray = array(
  3. 'field1' => 'value1',
  4. 'field2' => array('fieldarray1' => 'valuearray1'),
  5. 'field3' => array('fieldarray2' => array('fieldarray3' => array('fieldarray4' => 'valuearray4'))),
  6. );
  7.  
  8. $oMyConfig = new MyConfigArray($aSampleArray);
  9.  
  10. echo $oMyConfig['field1']; // value1
  11. echo $oMyConfig['field2']['fieldarray1']; // valuearray1
  12. echo $oMyConfig['field3']['fieldarray2']['fieldarray3']['fieldarray4']; // valuearray4
  13. ?>


Dzięki interfejsowi ArrayAcess otrzymujemy dostęp do danych obiektu jak do zwykłej tablicy, dlatego...

Plusy:
  • Możemy posłużyć się danymi w for(), foreach()
  • staroświedzki sposób dostępu z php 4
  • nie traktujemy danych jako obiekty (przeciwne teorii OOP)
Przykład numer 1 zastosowany jest na przykład w moim frameworku:
http://framework.vgroup.pl/expose-9a722aa0...965ef22bc4d.htm

Przykład drugi ma dobrego plusa: można użyć go jako normalnej tablicy, poslugując się chociażby for(), foreach(), count() itd.

Natomiast zastanawia mnie jeszcze jedna rzecz, a mianowicie połączenie tych dwóch sposobów dostępu do danych... wyszłaby ciekawa mieszanka, wartoby było spróbować.

Kwestię opinii pozostawiam Wam, być może nie dostrzegłem kolejnych plusów i minusów obu sposobów, być może niektóre z przedstawionych są błędne, zapraszam do dyskusji smile.gif

Pozdrawiam, Athlan smile.gif
ikioloak
wow nie wiedzialem ze jest interfejs (chyba o to ci chodzilo piszac iterator) ArrayAccess. W 1. przykladzie mozesz wlasnie zrobic tak aby klasa implementowala interfejs Iterator, dzieki czemu bedziesz mogl ja wykorzystywac w instrukcjach foreach.
Prph
Wszystko wydaje się piękne, ale w przypadku iteratora, spróbuj:

  1. <?php
  2. $mojObiekt->pierwszy->drugi->trzeci->czwarty;
  3. ?>


gdzie "pierwszy" już nie istnieje. php wywali błędy pomimo zastosowania isset (przynajmniej tak było, jak ja o tym pisałem).

Ogólnie nie przepadam za tymi interfejsami. Podoba mi się natomiast rozwiązanie typu:

  1. <?php
  2. $obiekt->get('pierwszy', 'drugi', 'trzeci');
  3. ?>



Jeżeli myle się co do 1. rozwiązania - proszę mnie wyprowadzić z błędu winksmiley.jpg

Adrian.
NuLL
Nie mylisz sie smile.gif
  1. <?php
  2. if($object->has('costam'))
  3. {
  4. ble ble
  5. }
  6. ?>

Tak powinno wygladac sprawdzanie czy cos jest. Pisanie klas kolekcyjnych bez metod typu has czy contains jest bledem poprostu.

Pozatym kolega Athlan powinien sie dowiedziec co to Iterator zamiast rozwazac rozne rozwiazania ze tak powiem winksmiley.jpg
Athlan
@NuLL, czym jest Iterator oczywiście wiem smile.gif Przesłowiłem się smile.gif Poza tym to nie jest iterator, tylko interfejs (przynajmniej tak jest napisane w książce Sebastiana Bergmana) smile.gif Chodzi mi tylko i wyłącznie dostęp do danych...

@Prph: do przykładu numer 1:
  1. <?php
  2. $aSampleArray = array(
  3. 'field1' => 'value1',
  4. 'field2' => array('fieldarray1' => 'valuearray1'),
  5. 'field3' => array('fieldarray2' => array('fieldarray3' => array('fieldarray4' => 'valuearray4'))),
  6. );
  7.  
  8. $oMyConfig = new MyConfigObject($aSampleArray);
  9.  
  10. var_dump( $oMyConfig->nie_istniejacy_klucz->fieldarray2->fieldarray3->fieldarray4 );
  11. ?>

zwóciło NULL... worriedsmiley.gif nie ma żadnego błędu...

Idę sobie do szkoły a tu: blink.gif wymyśliłem coś:

  1. <?php
  2.  
  3. final class MyConfigMulti implements ArrayAccess
  4. {
  5. private $_aParametrs = array();
  6.  
  7. public function __construct(array $aFields = array())
  8. {
  9. $this->_aParametrs = $aFields;
  10. }
  11.  
  12. public function __get($sParam)
  13. {
  14. return $this->_getParam($sParam);
  15. }
  16.  
  17. public function offsetGet($sParam)
  18. {
  19. return $this->_getParam($sParam);
  20. }
  21.  
  22. public function __set($sParam, $mValue)
  23. {
  24. return $this->_aParametrs[$sParam] = $mValue;
  25. }
  26.  
  27. public function offsetSet($sParam, $mValue)
  28. {
  29. return $this->_aParametrs[$sParam] = $mValue;
  30. }
  31.  
  32. public function offsetExists($sParam)
  33. {
  34. return (isset($this->_aParametrs[$sParam]) ? true : false);
  35. }
  36.  
  37. public function offsetUnset($sParam)
  38. {
  39. unset($this->_aParametrs[$sParam]);
  40. }
  41.  
  42. private function _getParam($sParam)
  43. {
  44. if(!isset($this->_aParametrs[$sParam]))
  45. return null;
  46.  
  47. if(is_array($this->_aParametrs[$sParam]))
  48. return new self($this->_aParametrs[$sParam]);
  49. else
  50. return $this->_aParametrs[$sParam];
  51. }
  52. }
  53.  
  54. ?>


Dostęp:

  1. <?php
  2. $aSampleArray = array(
  3. 'field1' => 'value1',
  4. 'field2' => array('fieldarray1' => 'valuearray1'),
  5. 'field3' => array('fieldarray2' => array('fieldarray3' => array('fieldarray4' => 'valuearray4'))),
  6. );
  7.  
  8. $oMyConfig = new MyConfigMulti($aSampleArray);
  9.  
  10. echo $oMyConfig['field1']; // value1
  11. echo $oMyConfig['field2']['fieldarray1']; // valuearray1
  12. echo $oMyConfig['field3']['fieldarray2']['fieldarray3']['fieldarray4']; // valuearray4
  13.  
  14. echo $oMyConfig->field1; // value1
  15. echo $oMyConfig->field2->fieldarray1; // valuearray1
  16. echo $oMyConfig->field3->fieldarray2->fieldarray3->fieldarray4; // valuearray4
  17. ?>


Tak tylko eksperymentuje, narazie nie wkładam w to wiele wagi, nie używam w projektach... stworzyłem na swoim poligonie śmieciatych, czasem przydatnych skryptów smile.gif

Co to tym myślicie? dry.gif Pytam TYLKO I WYŁĄCZNIE o mozliwości zastosowania, wygodę użycia itp. Wpadło mi do głowy to napislaem tongue.gif

Pozdrawiam, Athlan smile.gif

-- EDIT ---

Aaaaaa, @Prph, chodzi Ci o isset(), czy zmienna została zadeklarowana. W prypadku, który Ci podałem wynika że zwracamy NULL, co nie jest poprawne. Zgadzam się z Tobą i @NuLL'em, metoda has() jest jak najbardziej potrzebna... można ją owszem dodać do obu klas, jednak interesuje mnie sam dostęp do danych, wykonywanie operacji...
LEW21
Athlan, Iterator != Interfejs smile.gif Iterator to jeden z wbudowanych w php interfejsów. Więcej informacji jest na http://php.net/~helly/php/ext/spl/

PS. Co do przykładu użycia Iteratora - zerkinij do mojej klasy php SimpleDB (wysłanej na konkurs). Zastosowałem w niej i Iterator, i ArrayAccess, i zwykłą obiektową metodę dostępu do danych.
Athlan
Cytat
Athlan, Iterator != Interfejs

Wiem smile.gif

Na wstępie chciałbym powitać wszystkich forumowiczów, po długim okresie nieobecności z powodu bana smile.gif (pozdrawiam administrację tongue.gif )

Temat aktualny, większość problemów rozwiązanych poprzez użycie metody magicznej __isset(), więc po co has() ?

Kod klasy (prototyp, przyklad):

  1. <?php
  2.  
  3. class Rapide_Parametrs implements ArrayAccess
  4. {
  5. private $_aParametrs = array();
  6.  
  7. public function __construct(array $aFields = array())
  8. {
  9. $this->_aParametrs = $aFields;
  10. }
  11.  
  12. public function __get($sParam)
  13. {
  14. if(!isset($this->_aParametrs[$sParam]))
  15. return null;
  16.  
  17. if(is_array($this->_aParametrs[$sParam]))
  18. return new self($this->_aParametrs[$sParam]);
  19. else
  20. return $this->_aParametrs[$sParam];
  21. }
  22.  
  23. public function __set($sParam, $mValue)
  24. {
  25. return $this->_aParametrs[$sParam] = $mValue;
  26. }
  27.  
  28. public function __isset($sParam)
  29. {
  30. return (bool)isset($this->_aParametrs[$sParam]);
  31. }
  32.  
  33. public function __unset($sParam)
  34. {
  35. unset($this->_aParametrs[$sParam]);
  36. }
  37.  
  38. public function offsetGet($sParam)
  39. {
  40. return $this->__get($sParam);
  41. }
  42.  
  43. public function offsetSet($sParam, $mValue)
  44. {
  45. return $this->__set($sParam, $mValue);
  46. }
  47.  
  48. public function offsetExists($sParam)
  49. {
  50. return $this->__isset($sParam);
  51. }
  52.  
  53. public function offsetUnset($sParam)
  54. {
  55. $this->__unset($sParam);
  56. }
  57. }
  58.  
  59. ?>


Uzycie:

  1. <?php
  2. $aSampleArray = array(
  3. 'field1' => 'value1',
  4. 'field2' => array('fieldarray1' => 'valuearray1'),
  5. 'field3' => array('fieldarray2' => array('fieldarray3' => array('fieldarray4' => 'valuearray4'))),
  6. );
  7.  
  8. $oMyConfig = new Rapide_Parametrs($aSampleArray);
  9.  
  10. // obiekcik
  11. var_dump( $oMyConfig->field1 ); // value1
  12. var_dump( $oMyConfig->field2->fieldarray1 ); // valuearray1
  13. var_dump( $oMyConfig->field3->fieldarray2->fieldarray3->fieldarray4 ); // valuearray4
  14. var_dump( $oMyConfig->sdhcbdbc->sxasxasxas->sxasxasx->fieldarray2->fieldarray3->fieldarray4 ); // null
  15. var_dump( isset($oMyConfig->sdhcbdbc->fieldarray2->fieldarray3->fieldarray4) ); // false
  16. unset($oMyConfig->field3->fieldarray2->fieldarray3->fieldarray4); // nie dziala...
  17. var_dump( $oMyConfig->field3->fieldarray2->fieldarray3->fieldarray4 ); // null
  18.  
  19. // a teraz tabliczka
  20. var_dump( $oMyConfig['field1'] ); // value1
  21. var_dump( $oMyConfig['field2']['fieldarray1'] ); // valuearray1
  22. var_dump( $oMyConfig['field3']['fieldarray2']['fieldarray3']['fieldarray4'] ); // valuearray4
  23. var_dump( $oMyConfig['asxasxasxs']['sss']['vfdvdfvdf']['fieldarray2']['fieldarray3']['fieldarray4'] ); // null
  24. var_dump( isset($oMyConfig['asxasxasxs']['sss']['vfdvdfvdf']['fieldarray2']['fieldarray3']['fieldarray4'] ) ); // null
  25. unset( $oMyConfig['field3']['fieldarray2']['fieldarray3']['fieldarray4'] ); // nie dziala ...
  26. var_dump( $oMyConfig['field3']['fieldarray2']['fieldarray3']['fieldarray4'] ); // valuearray4
  27. ?>


Problem w linii:
unset($oMyConfig->field3->fieldarray2->fieldarray3->fieldarray4);
tak samo przy dostępie w ArrayAccess... dlaczego? Usówamy obiekt pochodny z tablicy stworzony przez __get(), a nie element tablicy. Póki co nie mam pojęcia jak to wykonać. Jeżeli macie jakieś pomysły to śmiało smile.gif

Pozdrawiam, Athlan smile.gif
Hacker
Moim zdaniem nie twórz za każdym getem nowych obiektów przechowuj zagnieżdżenia w tabeli
wystarczy wtedy sprawdzanie w __set i konstruktorze i tam tworzenie obiektów
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.