Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Data Objects i Data Access Objects
become
post
Post #1





Grupa: Zarejestrowani
Postów: 88
Pomógł: 0
Dołączył: 12.01.2007

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


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

Ten post edytował become 30.11.2007, 12:44:08
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
splatch
post
Post #2





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

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


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. (IMG:http://forum.php.pl/style_emoticons/default/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. ?>
Go to the top of the page
+Quote Post

Posty w temacie


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: 9.10.2025 - 23:24