Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Data Objects i Data Access Objects
Forum PHP.pl > Forum > PHP > Object-oriented programming
become
Witam. Chciałbym trochę rozwinąć myśl NoiseMC. Bo Twoje podejście mnie lekko zaintrygowało.

Rozumiem że wynika ono z modelu MVC ?

Mam pytanie odnośnie tego co napisłeś.
Jak skorelowac ze sobą konkretny obiekt Model i nie-Model ?
Chodzi mi o to, że jeżeli utworzę dwie klasy to bede mial 2 obiekty. Jezeli Data Object ma przechowywać tylko dane, to rozumiem, że nie powinien on mieć wogóle metod manipulującymi danymi ? Nawet gettery ?

Załużmy taką sytuację.
pobieram z bazy Artykul. Chcialbym zmienic mu opis i zrobic update danych na bazie.
Czy dobrze rozumiem, ze klasa Data Access Objects zajmuje sie pobieraniem danych i zwracaniem obiektu a po poprawieniu przekazuje obiekt to Data Access Objects i go zapisuje ?
Chyba ze umiescic go w klasie model na stale. No nie wiem.

Np. Mam taką klase

  1. <?php
  2. class ArticleInfo() {
  3.  
  4.  var $id;
  5.  var $title;
  6.  var $info;
  7.  var $oAuthor;
  8.  
  9.  function __construct ($id=null, $title=null, $info=null, Author $author=null) {
  10. $this->id=$id;
  11. $this->title=$title;
  12. $this->info=$info;
  13. $this->oAuthor=$author;
  14.  }
  15.  
  16.  function getTitle() {
  17. return $this->title;
  18.  }
  19. }
  20.  
  21.  
  22. class ArticleInfo_Model($oDB) {
  23.  
  24.  var $oDB;
  25.  
  26.  function getArticleInfoById($id) {
  27.  $sQ="SELECT *
  28.  FROM articles
  29.  WHERE id_article=?";
  30.  
  31. $aArticle=$this->$oDB->getRow($sQ, array($id));
  32.  
  33. if (!is_null($aArticle) {
  34.  $modelAuthor=new Author_Model($this->oDB);
  35.  $oAuthor=$modelAuthor->getAuthor($aArticle['authorid');
  36.  return new ArticleInfo($id, $aArticle['title'], $aArticle['info'], $oAuthor);
  37. }
  38.  }
  39. }
  40.  
  41. class Author() {
  42.  
  43.  var $id;
  44.  var $firstname;
  45.  var $lastname;
  46.  var $email;
  47.  var $login;
  48.  var $password;
  49.  
  50.  function __construct($id=null, $firstname=null, $lastname=null, $email=null, $login=null, $password=null) {
  51. $this->id=$id;
  52. $this->firstname=$firstname;
  53. $this->lastname=$lastname;
  54. $this->email=$email;
  55. $this->login=$login;
  56. $this->password=$password;
  57.  }
  58.  
  59.  function getId() {
  60. return $this->id;
  61.  }
  62.  
  63.  function getFirstName() {
  64. return $this->firstname;
  65.  }
  66.  
  67.  
  68. }
  69.  
  70. class Author_Model($oDB) {
  71.  
  72.  var $oDB;
  73.  
  74.  function getAuthor($id) {
  75.  
  76. $sQ="
  77. SELECT * FROM author WHERE id_author=?
  78. ";
  79.  
  80. $aAuthor=$this->$oDB->getRow($sQ, array($id));
  81.  
  82. if (!is_null($aAuthor) {
  83.  return new Author($id, $aAuthor['firstname'], $aAuthor['lastname'], $aAuthor['email'], $aAuthor['login'], $aAuthor['password']);
  84. }
  85.  }
  86. }
  87. ?>


i teraz wykorzystanie

  1. <?php
  2. $oDB=new DB();
  3.  $oDB->connect(DSN);
  4.  
  5.  $html=new Smarty();
  6.  
  7.  $modelArticleInfo=new ArticleInfo_Model($oDB);
  8.  $oArticleInfo=$modelArticleInfo->getArticleInfoById(34);
  9.  
  10.  $html->assign("article",$oArticleInfo);
  11. ?>


W ten sposób wyciągam dane konkretnego artykułu (po jego ID).
I co o tym myslicie ? Czy to jest prawidłowo ?

Czy moglbym stworzyc np.
klasę Articles_Model, ktora zawieralalby metody zwracajace:
1. obiekt ArtykulInfo (class ArticleInfo)
2. obiekt Artykul (class Article)
3. lista info artykulow danej kategorii -> tablica obiektow class ArticleInfo
splatch
Data Access Object - zwraca i zapisuje obiekty. Może (chociaż nie musi) nadzorować zarządzanie transakcjami bazodanowymi.

Model w rozumieniu MVC to dane, chociaż wraz z przejściem do PHP pojęcie to zostało wypaczone. Teraz wszystko co zwraca tablice i odwołuje się do bazy to model. Nie panowie - model w podejściu obiektowym to z pewnością nie jest tablica. Zamiast modelu powinien występować duet Domain Object (zachęcam do przeczytania mojej noty na ten temat) oraz DAO. Teraz jak to wygląda - obiekty mają wewnątrz powiązania a DAO jest fasadą dostępu do obiektów - innymi słowy DAO zwraca już obiekty danego typu. Nas, z perspektywy użytkowników interfejsu to w ogóle nie interesuje - po prostu dajemy ID dostajemy obiekt. Pod spodem może być XML, baza danych, plik tekstowy, wszystko, z czego da się wyłuskać dane. Zyskujemy w ten sposób jednolitą definicję obiektów biznesowych w pełni niezależną od źródła danych. "Obiekty" mogą współpracować niezależnie od miejsca pochodzenia - nic nie stoi na przeszkodzie by odczytanego z XML autora wrzucić do książki, którą mamy w bazie, ponieważ DAO bazując na definicji obiektów bez problemu to wszystko zapisze. smile.gif
Poniżej przedstawiam przykład napisany "na szybko".

  1. <?php
  2. /**
  3.  * Umowny interfejs dla zapisywanych obiektów.
  4.  **/
  5. interface Persistable {
  6. function getId();
  7. }
  8.  
  9. /**
  10.  * Definicja wspólnych metod dla wszystkich data-access-object'ów.
  11.  **/
  12. interface GenericDAO {
  13.  
  14. // pobranie pojedynczego rekordu
  15. function getById(int $id);
  16.  
  17. // zapisanie - wstawienie bądź aktualizacja
  18. function save(Persistable $object);
  19.  
  20. // usunięcie rekordu
  21. function remove(Persistable $object);
  22. }
  23.  
  24. /**
  25.  * Metody specyficzne dla autora.
  26.  **/
  27. interface ArticleDAO extends GenericDAO {
  28.  
  29. // pobranie książek po autorze.
  30. function getByAuthor(int $id);
  31.  
  32. }
  33.  
  34. // implementacja bazowa
  35. abstract class GenericDAOImpl implements GenericDAO {
  36.  
  37. // obsługiwany typ 
  38. private $className;
  39.  
  40. public function __construct($className) {
  41. $this->className = $className;
  42. }
  43.  
  44. // nazwa obsługiwanego typu
  45. protected final function getClassName() {
  46. return $this->className;
  47. }
  48.  
  49. // pobranie po identyfikatorze
  50. protected abstract function findById(int $id);
  51.  
  52. // zapisanie obiektu
  53. protected abstract function doSave(Persistable $id);
  54.  
  55. // usunięcie obiektu
  56. protected abstract function doRemove(Persistable $id);
  57.  
  58. protected final function verify(Persistable $obj) {
  59. if (!($obj instanceof $this->getClassName()) {
  60. throw new DAOException('Unexpected type ' . get_class($obj)
  61.  . ', expected ' . $this->getClassName());
  62. }
  63. }
  64.  
  65. // pobranie pojedynczego rekordu
  66. public final function getById(int $id) {
  67. return $this->findById($id);
  68. }
  69.  
  70. // zapisanie - wstawienie bądź aktualizacja
  71. public final function save(Persistable $object) {
  72. verify($object);
  73. return $this->doSave($object);
  74. }
  75.  
  76. // usunięcie rekordu
  77. function remove(Persistable $object) {
  78. verify($object);
  79. return $this->doRemove($object);
  80. }
  81. }
  82. /**
  83.  * Implementacja DAO dla baz danych.
  84.  **/
  85. class SQLGenericDAO extends GenericDAOImpl {
  86.  
  87. // zwraca Persistable
  88. protected abstract function hydrate(array $data);
  89.  
  90. protected function buildSelect(int $id, $table = null) {
  91. if (is_null($table)) {
  92. $table = strtolower($this->getClassName()) ;
  93. }
  94. return 'select * from ' . $table . ' where '. $table .'_id = ' . $id;
  95. }
  96.  
  97. protected function execute(string $sql) {
  98. // tutaj jakiś kod związany z wykonaniem zapytania.
  99.  
  100. if ($resultSize > 1) {
  101. // dla wszystkich wierszy tworzymy obiekty
  102. foreach ($pers as $k => $v) {
  103. $pers[$k] = $this->hydrate($v);
  104. }
  105. } else {
  106. $pers = array($this->hydrate($row));
  107. }
  108. return $pers;
  109. }
  110.  
  111. // pobranie po identyfikatorze
  112. protected final function findById(int $id) {
  113. $pers = $this->execute($this->buildSql($id));
  114. if (!isset($pers[0])) {
  115. throw new ObjectNotFoundException($this->getClassName(), $id);
  116. }
  117. verify($pers[0]);
  118. return $pers[0];
  119. }
  120.  
  121. // zapisanie obiektu
  122. protected function doSave(Persistable $object) {
  123. return $this->insert($this->getClassName(), $object);
  124. }
  125.  
  126. // usunięcie obiektu
  127. protected function doRemove(Persistable $object) {
  128. // Persistable ma zawsze określone ID.
  129. return $this->delete($this->getClassName(), $object->getId());
  130. }
  131. }
  132.  
  133. // i wreszcie nasza implementacja ... 
  134. class AuthorSQLDAO extends SQLGenericDAO implements AuthorDAO {
  135.  
  136. public function __construct() {
  137. parent::__construct('Author');
  138. }
  139.  
  140. protected function hydrate(array $row) {
  141.  $author = new Author($row['author_id']);
  142.  $author->setName($row['author_name']);
  143.  // etc...
  144.  return $author;
  145. }
  146.  
  147. // w pośpiechu źle zrobiłem tą metodę - można skorzystać do tego z getById..
  148. public function getByAuthor(int $id) {
  149. $pers = $this->execute($this->buildSql($id)); // tu powinniśmy dostać tablicę
  150.  
  151. foreach ($pers as $obj) {
  152. verify($obj);
  153. }
  154.  
  155. return $pers;
  156. }
  157. }
  158.  
  159. // a może inna wariacja... ?
  160. abstract class AuthorXMLDAO extends XMLGenericDAO implements AuthorDAO {}
  161. ?>
become
przyjmując ze dopiero zaczynam OOP - to co napisales to dla mnie jakaś ciezka abstrakcja smile.gif

ale przeanalizuje o co w tym kodzie chodzi. dzieki ogromne.
splatch
Dobrze, klika słów wyjaśnienia do kodu powyżej.

Persistable to interfejs. Potrzebujemy go by móc stworzyć generyczne DAO posługujące się minimalną ilością danych, stąd wymagamy tylko identyfikatora. Nazwa klasy to nazwa naszej tabelki. Jest to uproszczone założenie, ale w razie czego można sobie podmapować nazwy klas do nazw tabel w bazie danych.


GenericDAO ponownie interfejs. Posłuży on nam do stworzenia bazowego DAO. Wszystkie obiekty, które obsługujemy możemy ogólnie rzecz biorąc odczytać, zapisać i usunąć. To jest własnie to DAO nie określamy w nim jeszcze żadnego zachowania z poszczególnym źródłem danych a tylko zapewniamy bardzo, bardzo ogólną definicję.

ArticleDAO jest to interfejs rozszerzający GenericDAO. Powiedzmy, że jest coś co powoduje, że chcemy odczytać autorów korzystając z innego pola niż ID - na przykład roku urodzenia. Wtedy tworzymy metodę getAuthorsByAge($age). W tym momencie wszystkie implementacje DAO dla autorów powinny zatroszczyć się o dostarczenie odpowiednich metod.

GenericDAOImpl klasa abstrakcyjna w której zasadniczon weryfikujemy tylko typ obiektu. Ze względu na to, że PHP nie wspiera typów generycznych (szablonów) pojawia się metoda verify. Wyrzuca ona wyjątek gdy typ przekazanego w argumencie obiektu nie zgadza się z typem jaki ma obsługiwać dana instancja DAO. Poza weryfikowaniem danych nie ma tu nic więcej ot, delegowanie metod by obiekty zawsze były weryfikowane (final przy implementacjach metodach zdefiniowanych w GenericDAO).

SQLGenericDAO abstrakcyjna klasa zbudowana w oparciu o GenericDAOImpl, która zapewnia podstawowe operacje związane z bazą danych - odczyt, generowanie prostych zapytań SQL i tak dalej. Jest to pierwszy z poziomów, który związany jest z konkretnym źródłem danych. Na bazie tej klasy możemy tworzyć sobie już specyficzne implementacje AuthorSQLDAO, BookSQLDAO, CategorySQLDAO i tak dalej. Wszystko co wymagamy od implementacji to dodanie metody hydrate, która stworzy z wiersza bazy danych obiekt oraz przekazanie nazwy klasy jaką chce to DAO obsługiwać (odwołanie do parent::__construct to w gruncie rzeczy konstruktor GenericDAOImpl).

XMLGenericDAO to tylko pomysł by pokazać, że możemy zbudować w oparciu o GenericDAOImpl klasę, która może bez problemów odczytywać dane z innego źródła danych. Tu również pojawiła by się metoda hydrate, która by tworzyła obiekty na bazie danych z XML (przekształcenie DOMElement w jakiś charakterystyczny obiekt).

AuthorSQLDAO ostatni węzeł naszej hierarchii zapewniający odczyt autorów z bazy danych. Pojawia się w nim troszkę mylna implementacja metody getByAuthor z interfejsu AuthorDAO. Chciałem tu pokazać użycie tego co nam zapewnia implementacja SQLGenericDAO - odczyt danych to tylko proste odwołania do metod.

AuthorXMLDAO no to też czysta abstrakcja - coś analogicznego do w/w DAO, które by się sprowadziło do implementacji paru metod.

Jeśli macie pytania, sugestie, wątpliwości, zapraszam do rozmowy. Razem uda nam się dojść do konsensusu smile.gif.
become
wiesz co. lekko skumałem o co ci chodzi w takim podejsciu.
niemniej ja zakladam, ze system, ktory pisze bedzie oparty o baze mysql i nie przewiduje trzymania danych np. w plikach xml.

Natomiast jest to dosc ciekawe. Np. mozna zastosowac ten mechanizm podczas tworzenia np. jakiegos prostego CMS'a,
ktory bedzie umozliwial zapisywanie danych wg. wyboru (pliki proste, baza mysql, itd).

To nad czym teraz pracuje to serwis ala interia360.pl (no na pwno nie ta skala).
Generalnie jest
1. Uzytkownik (czytelnik, autor)
2. Kategoria i podkategoria
3. Artykul
4. Wstep artykulu (lista takich wstepow jest generowana dla kazdej kategorii i podkategorii)
5. Lista komentarzy artykulu.
6. komentarz.


Kazdy artykul mozna ocenic po zalogowaniu 1 raz. Kazdy artykul ma zliczana ilosc czytań.

Zaczalem pisac proceduralnie i mialem juz troche kodu naklepane ale stwierdzilem, ze jednak lepiej w koncu nauczyc sie OOP.
Mysle ze dziedzina serwisu doskonale sie do tego nadaje.

Niemniej interfejsy i abstakcje to jeszcze dla mnie za wysoko.

Bo widzisz, to co zaproponował mi NoiseMC powoduje ze mam wiele pytań. To co proponujesz Ty to juz straszna abstakcja za którą niemniej jestem bardzo wdzięczny, bo naprawde nie domyslalem sie ze mozna to tak zorganizowac. Jest to bardzo logiczne i pewnie z czasem doszedlbym do tego. Ale po co sie domyslac jak mozna sie zapytac. Splatch - twoj blog dodalem do ulubionych smile.gif
Pytań miałbym bardzo, bardzo duzo ale jednak chcialbym juz zaczac to pisac smile.gif
Cysiaczek
To po prostu użyj Propela - szkielet prostego serwisu zrobisz w kilka godzin i zapomnisz, czym są zapytania SQL haha.gif.

Pozdrawiam.
become
uzycie propela nie bedzie oznaczalo ze naucze sie myslec w sposob obiektowy na poziomie jaki prezentuje splatch.
a chce sie tego nauczyc.
splatch
Cytat(Cysiaczek @ 30.11.2007, 16:16:42 ) *
To po prostu użyj Propela - szkielet prostego serwisu zrobisz w kilka godzin i zapomnisz, czym są zapytania SQL haha.gif.

@Cysiaczek wszyscy dobrze wiemy, że Propel nie jest złotym środkiem, a w przypadku DAO nie ma problemu by wykorzystać ORM. Wystarczy nam przecież obiekt, który bez większych problemów da się zapisać. Problem w tym, że Propel dorzuca swoje metody etc, nie wspiera obiektów lekkich, przeźroczystych i to utrudnia wykorzystanie go do tworzenia warstwy domenowej. Jakkolwiek przy odrobinie wysiłku dało by się. Dla zainteresowanych - w aplikacjach opartych na Springu mimo wykorzystania potężnego narzędzia jakim jest bez wątpienia Hibernate, tworzy się interfejsy oraz ich implementacje, które dopiero pod spodem korzystają z tego co oferuje ORM.

Spójrzmy na klasę DaoSupport:
afterPropertiesSet() - walidacja danych
checkDaoConfig() - walidacja konfiguracji
initDao() - inicjowanie DAO

Następnie mamy do dyspozycji rozszerzenia dla różnych bibliotek. Od ogólnych implementacji - JPA poprzez Hibernate i Toplink po SqlMap (iBatis) i JDBC (czytaj natywne zapytania).
CciDaoSupport, HibernateDaoSupport, JdbcDaoSupport, JdoDaoSupport, JpaDaoSupport, SqlMapClientDaoSupport, TopLinkDaoSupport.

Wierz mi, że nieprzypadkowo te klasy trafiły do Springa - we większości projektów opartych na tym frameworku, które widziałem do tej pory na oczy, występuje dao dla ORM oraz JDBC. Wynika to z tego, że część operacji po prostu nie jest przepychana przez narzędzia mapujące a przez zapytania. Powiedzmy, spore partie danych są wrzucane przez masowe inserty, ponieważ użycie zasobów przez ORM zabiło by serwer aplikacyjny.

Podobnie moi drodzy ma się sprawa z naszymi przyszłymi projektami. Warto sobie budować "core", który bezproblemowo przechodzi z jednego projektu do drugiego by w przyszłości zaoszczędzić czas. Pojawił się tu temat Springa - jest to narzędzie bardzo popularne wśród developerów Javy, momentami aż za bardzo, aczkolwiek skala jego wykorzystania wynika z tego, że jest on bardzo łatwy w adaptacji. Gdy dobrze skonstruujesz sobie abstrakcję przy DAO będziesz mógł je użyć wszędzie - niezależnie od projektu i użytych bibliotek.
NoiseMc
Become to co zaproponowalem to jest najprostsza implementacja modelu o ktorym pisze Splatch i byc moze dobry piewszy krok w kierunku myslenia obiektowego.
To co zaproponowal Splatch to bardzo zaawansowana implementacja z wykorzystaniem interfejsow i klas abstrakcyjnych, dobrze byloby gdybys to tez rozumial aczkolwiek na poczatek i gdy pracujesz nad projektem sam moze nie bedziesz musial sie na niej wzorowac. Interfejsy i klasy abstrakcyjne przydaja sie w momencie kiedy projekt staje sie duzy i pracuje nad nim kilka lub kilkanascie osob, za ich pomoca kontrolujesz porzadek w systemie i narzucasz innym developerom jak ma wygladac API systemu tak, aby wszsytko wygladalo tak jak zaplanowal sobie architekt, zeby nie bylo samowolki i zeby system byl spojny.

Swoja droga tez nie jestem biegly w projektowaniu systemow i widze dzieki Wam ze moje myslenie idzie w dobra strone winksmiley.jpg Ciesze sie ze poruszylismy ten temat.

Nawiazujac jeszcze do kodu Become, zastanawiam sie czy obiekty pomocnicze, ktore zawieraja obiekty DO powinny byc tworzone przez DAO na podstawie id i przypisywane do DO czy tez DO powinien sobie tworzyc je sam korzystajac z ich DAO.

Dla przykladu zarzuce:

Data Object
  1. <?php
  2. class Offers_Offer
  3. {
  4. public function __construct ($offerID, $urlSlug, $abbreviation, $name, $isFirst)
  5. {
  6. $this->offerID = $offerID;
  7. $this->urlSlug = $urlSlug;
  8. $this->abbreviation = $abbreviation;
  9. $this->name = $name;
  10. $this->isFirst = $isFirst;
  11.  
  12. $headerImageModel = new Offer_Header_Model ();
  13. $this->headerImage = $headerImageModel->getHeaderImageByOffer ($this);
  14.  
  15. $contentPagesModel = new Offer_Content_Model ();
  16. $this->contentPages = $contentPagesModel->getContentPagesByOffer ($this);
  17.  
  18. $metaTagsModel = new Offer_Meta_Model ();
  19. $this->metaTags = $metaTagsModel->getMetaTagsByOffer ($this);
  20. }
  21.  
  22. }
  23. ?>


Data Access Object
  1. <?php
  2. class Offer_Model extends Base_Model
  3. {
  4. public function __construct ()
  5. {
  6. $offerList = $this->aycAccess->getSchoolList ();
  7.  
  8. foreach ($offerList as $offer)
  9. {
  10. $this->offerList[$offerID] = new Offer_Offer ($offer['schoolID'], $offer['url_slug'], $offer['abbrev'], $offer['school_name'], $isFirst);
  11. }
  12. }
  13. }
  14. ?>
become
Moze inaczej.

Spróbujmy zrobić na przykładzie takiej funkcjonalności.
Nie traktujcie tego że chcę iść na łatwiznę i szukam gotowców. Znajomy, który pracuje w gratka.pl polecił mi nauke na przykładach smile.gif
Wiec próbuje stworzyć takie przykłady.

Aby było jak najprościej przyjmijmy ze nie stosujemy interfejsów i klas abstakcyjnych.

Załóżmy że chcemy mieć następujące obiekty.

1. ArtykulWstep (pola: artykul_id, tytul, wstep)
2. Artykul (pola: autor, artykul_id, tytul, wstep, tresc)
3. Autor (id, imie,nazwisko)

oraz chcielibyśmy uzyskać konkretny artykuł po jakimś ID oraz listę artykulWstep z danej kategorii.



Przede wszystkim.
  1. <?php
  2.  
  3. class Autor_DO {
  4.  
  5.  var $id;
  6.  var $imie;
  7.  var $nazwisko;
  8.  
  9.  function __construct($id=null, $imie=null, $nazwisko=null) {
  10. $this->id=$id;
  11. $this->imie=$imie;
  12. $this->nazwisko=$nazwisko;
  13.  }
  14. }
  15.  
  16. class Autor_SQL_DAO {
  17.  
  18.  var $DB;
  19.  
  20.  function __construct($DB=null) {
  21. if (is_null($DB)) return null;
  22. $this->DB=$DB;
  23.  }
  24.  
  25.  function getAutorById($id=null) {
  26. if (is_null($id)) return null;
  27. $sql="
  28. SELECT *
  29. FROM autor
  30. WHERE autor_id=?
  31. ";
  32.  
  33. $aRes=$this->DB->getRow($sql, array($id));
  34. if (is_array($aRes) and count($aRes)==1) {
  35.  return new Autor_DO($aRes['autor_id'], $aRes['imie'], $aRes['nazwisko']);
  36. }
  37. return null;
  38.  }
  39. }
  40.  
  41. class ArtykulWstep_DO {
  42.  
  43.  var $artykul_id;
  44.  var $tytul;
  45.  var $wstep;
  46.  
  47.  function __construct($id=null, $tytul=null, $wstep=null) {
  48. $this->artykul_id=$id;
  49. $this->tytul=$tytul;
  50. $this->wstep=$wstep;
  51.  }
  52. }
  53.  
  54. class Artykul_DO extends ArtykulWstep_DO {
  55.  
  56.  var $oAutor;
  57.  var $tresc
  58.  
  59.  function __construct($id=null, $tytul=null, $wstep=null, $tresc=null, Autor_DO $autor=null) {
  60. $this->tresc=$tresc;
  61. $this->oAutor=$autor;
  62. parent::__construct($id, $tytul, $wstep);
  63.  }
  64. }
  65.  
  66. class Artykul_SQL_DAO {
  67.  
  68.  var $DB;
  69.  
  70.  function __construct($DB) {
  71. $this->DB=$DB;
  72.  }
  73.  
  74.  function getArtykulById($id=null) {
  75. if (is_null($id)) return null;
  76. $sql="
  77. SELECT *
  78. FROM artykul
  79. WHERE artykul_id=?
  80. ";
  81.  
  82. $aRes=$this->DB->getRow($sql, array($id));
  83. if (is_array($aRes) and count($aRes)==1) {
  84.  $autor_sql_dao=new Autor_SQL_DAO($this->DB);
  85.  $oAutor=$autor_model->pobierzAutora($aRes['autor_id']); // obiekt autor
  86.  return new Artykul_DO($aRes['artykul_id'], $aRes['tytul'], $aRes['wstep'], $aRes['tresc'], $oAutor);
  87. }
  88. return null;
  89.  }
  90.  
  91.  /*
  92.   Zwraca obiekt ArtykulWstep_DO
  93.  */
  94.  function getArtykulWstepById($id=null) {
  95. if (is_null($id)) return null;
  96. $sql="
  97. SELECT *
  98. FROM artykul
  99. WHERE artykul_id=?
  100. ";
  101.  
  102. $aRes=$this->DB->getRow($sql, array($id));
  103. if (is_array($aRes) and count($aRes)==1) {
  104.  return new ArtykulWstep_DO($aRes['artykul_id'], $aRes['tytul'], $aRes['wstep']);
  105. }
  106. return null;
  107.  }
  108.  
  109.  /* 
  110.   Zwraca tablice obiektow ArtykulWstep_DO z kategori o podanym ID
  111.  */
  112.  function getListaArtykulowWstepByCategoryId($id=null) {
  113. if (is_null($id)) return null;
  114. $sql="
  115. SELECT *
  116. FROM artykul
  117. WHERE kategoria=?
  118. ";
  119.  
  120. $aRes=$this->DB->getAll($sql, array($id));
  121. if (is_array($aRes) and count($aRes)>=1) {
  122.  for ($i=0; $i<count($aRes); $i++) {
  123. $aoArtykulyWstep[$i]=new ArtykulWstep_DO($aRes['artykul_id'], $aRes['tytul'], $aRes['wstep']);
  124.  }
  125.  return $aoArtykulyWstep;
  126. }
  127. return null;
  128.  }
  129. }
  130. ?>


co o tym myslicie ? Czy jako początkujacy w OOP moglbym tak to zrobic ?

wlasnie sobie tak mysle, czy klasa User_DAO nie powinna rozszerzać możliwosci klasy DO ?

czyli byloby:

  1. <?php
  2. class User {
  3.  
  4. }
  5. ?>


i

  1. <?php
  2. class User_DAO extends User {
  3. }
  4. ?>


questionmark.gif
Bo naprawde, jezeli rozdziele te dwie klasy, to jak mam operowac na danych obiektu.
Zalozmy taka sytuacje. Uzytkownik po zalogowaniu chce zmienic swoje dane osobowe.
klasa User_DAO zwraca obiekt User z danymi. Przekazuje te dane do formularza. Po ich sprawdzeniu dane te chce zapisac.
To gdzie powinny trafic dane z formularza ? Do obiektu User, czy do obiektu User_DAO, a może do obiektu User, a obiekt User przekazać do obiektu User_DAO, który zapisze dane do bazy.
Normalnie chyba jednak powinienem najpierw robic jak najprościej, bo siedze juz 3 godziny nad klasa Authentication i User i co chwile zmieniam koncepcje.
NoiseMc
No ja sobie tworze obiekt DO i przekazuje go do DAO:

  1. <?php
  2. class ProductsController
  3. {
  4. public function saveAction ()
  5. {
  6. $productID = (int)$this->request->getParam ('id');
  7.  
  8. $product = new Products_Product ();
  9.  
  10. $postData = $this->request->getPost ();
  11.  
  12. if (! empty ($postData))
  13. {
  14. $product->productID = $productID;
  15. $product->name = $postData['name'];
  16. $product->urlSlug = $postData['urlSlug'];
  17. $product->copy = $postData['copy'];
  18.  
  19. $this->productsModel->save ($product);
  20. }
  21. }
  22. }
  23. ?>


Pominalem tutaj walidacje i filtrowanie danych wejsciowych ale to zupelnie inny temat
splatch
Cytat(become @ 1.12.2007, 17:25:42 ) *
wlasnie sobie tak mysle, czy klasa User_DAO nie powinna rozszerzać możliwosci klasy DO ?

czyli byloby:

  1. <?php
  2. class User {
  3.  
  4. }
  5. ?>


i

  1. <?php
  2. class User_DAO extends User {
  3. }
  4. ?>

Nie, nie powinna. Nie wpychaj dziedziczenia tam gdzie jest ono zbyteczne. Przed stworzeniem hierarchii pomyśl co wspólnego mają klasy. Często przykładem dla pokazania dziedziczenia są relacje rodzice - dzieci czy też pojazd - auto. W Gdyby przełożyć dziedziczenie UserDAO z User na świat rzeczywisty mielibyśmy twierdzenie, że słoń jest potomkiem bloku mieszkalnego..
become
NoiseMC.

Widze ze controler tez masz stworzony jako klasę.
Ja do tej pory mialem kontroler zbudowany tak, ze ładowałem odpowiedni plik php na podstawie parametru, ktory okreslal kontroler, a funkcja z kontrolera byla wybierana na podstawie paraemtru funkcji.
np. jezeli w adresie bylo /?c=user&f=commisionlist

to w index.php ładowałem główny plik kontrolera czyli user.php
tam mialem switch po parametrze $_GET['f'] i wtedy w
case 'commisionlist' wykonywały się reszta operacji.

ja na razie staram sie przynajmniej wprowadzic obiekty do danych. niemniej podoba mi sie Twoje podejscie.
Kontroler jako klasa i w kontrolerze tworzone sa obiekty DAO i obiekty DA. Zapewne w contolerze rowniez tworzysz obiekty weryfikujace dane.

Mozesz zdradzic czy twoj sposob utworzenia logiki kodu jest gdzies opisany w jakiejsc ksiazce, bo nie ukrywam ze bardzo mi sie podoba.
Moglbys cos polecic co warto przeczytac ? A moze moglbys podzielic sie jakims wiekszym kodem lub wskazac jaki soft jest podobnie napisany, ktory jest ogolnie dostepny. chetnie bym cos takiego przeanalizowal ?

Inna sprawa ze czytam sobie PHP5 Zaawansowane programowanie i tam pisza, że klasa DataManager powinny byc statyczne. Czy DataManager to DAO ? Pisze tez, że nie powinno się umieszczac obiektu w innym obiekcie, ale tworzyc tzw. Kolekcje.

Oj ludzie im bardziej wnikam w OOP tym bardziej mnie ono przeraza smile.gif
NoiseMc
No ja sie sugeruje tym co jest opisane tutaj i tutaj i co pisza ludzie na forum oraz korzystam z Zend Framework
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.