Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Czy warto stosować PEAR::DB w OOP oraz czy przechowywać dane w tabliczy czy w osobnych zmiennych ?
Forum PHP.pl > Forum > PHP > Object-oriented programming
become
mam taką klasę

  1. <?php
  2. class Autor() {
  3.  
  4.  var $oDB=null; # obiekt PEAR:biggrin.gifB;
  5.  var $aAutor=null; # zmienna przechowujaca dane autora
  6.  
  7.  function Autor($oDB=null) {
  8. if (!is_null($oDB)) $this->oDB=$oDB;
  9.  }
  10.  
  11.  function dbGetAutorById($id=null) {
  12.  
  13. if (is_null($id) return null;
  14.  
  15. $aQ="
  16.  SELECT *
  17.  FROM autor
  18.  WHERE id=?
  19. ";
  20.  
  21. $aA=$this->oDB->getRow($sQ, array($id), DB_FETCHMODE_ASSOC);
  22. if (is_array($aA) and count($aA)==1) $this->aAutor=$aA;
  23.  }
  24. }
  25. ?>


i pozniej sposob wykorzystania tego

  1. <?php
  2. include "PEAR/DB.php"; 
  3.  
  4.  $oDB=new DB();
  5.  $oDB->connect(DSN);
  6.  
  7.  $autor=new Autor($oDB);
  8.  $autor->dbGetAutorById(234);
  9. ?>


mam pytanie. czy mozna ją tą zbudować ? czy uzycie obiektu klasy PEAR:: DB i przekazanie jej do innej klasy w powyzszy sposob jest prawidlowe ? Czy wogole warto uzywać pakiet PEAR:: DB cyz moze cos innego ?

Drugie pytanie. Czy reprezentawac dane autora jako tablice czy raczej stworzyc osobne zmienne na np. pole imie, nazwisko, email, ktore bedą reprezentowac kolumny w tabeli ?
NoiseMc
Ja mam osobno Data Objects i Data Access Objects. Data Objects przechowuja tylko dane, a Data Access Objects pobieraja dane z bazy i na ich podstawie zwracaja tablice wypelnionych danymi z bazy Data Objects czyli na przyklad:
  1. <?php
  2. class Products_Product
  3. {
  4. public $productID;
  5. public $categoryID;
  6. public $name;
  7. public $urlSlug;
  8. public $copy;
  9. public $displayOrder;
  10.  
  11.  public function __construct ($productID = null, $categoryID = null, $name = null, $urlSlug = null, $copy = null, $displayOrder = null
  12. {
  13. $this->productID = $productID;
  14. $this->categoryID = $categoryID;
  15. $this->name = $name;
  16. $this->urlSlug = $urlSlug;
  17. $this->copy = $copy;
  18. $this->displayOrder = $displayOrder;
  19. }
  20. }
  21. ?>

  1. <?php
  2. class Products_Model extends Base_Model 
  3. {
  4. public function getAll ()
  5. {
  6. $query = 'SELECT * FROM ' . $this->config->database->prefix . 'products ORDER BY DisplayOrder DESC';
  7.  
  8. $statement = $this->db->prepare ($query);
  9.  
  10. $statement->execute ();
  11.  
  12. while ($product = $statement->fetch ())
  13. {
  14. $products[] = new Products_Product ($product['ProductID'], $product['CategoryID'], $product['Name'], $product['UrlSlug'], $product['Copy'], $product['DisplayOrder'], $product['MetaTitle'], $product['MetaDescription'], $product['MetaKeywords']);
  15. }
  16.  
  17. if (empty ($products))
  18. {
  19. return null;
  20. }
  21.  
  22. return $products;
  23. }
  24. }
  25. ?>

Co do DB to uzywam PDO, ma chyba taka sama funkcjonalnosc jak PEAR:DB, a jest wbudowane w PHP 5 i obiekt DB tworze sobie w klasie bazowej dla Data Access Object:
  1. <?php
  2. class Base_Model 
  3. {
  4. protected $db;
  5. protected $config;
  6.  
  7. public function __construct ()
  8. {
  9. $this->config = Zend_Registry::get ('config');
  10.  
  11. $this->db = new PDO ('mysql:host=' . $this->config->database->host . ';dbname=' . $this->config->database->dbname . '', $this->config->database->username, $this->config->database->password);
  12.  
  13. $this->db->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  14. $this->db->setAttribute (PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1);
  15. }
  16. }
  17. ?>


Korzystam z tego tak:
  1. <?php
  2. $productsModel = new Products_Model ();
  3. $products = $productsModel->getAll ();
  4. ?>

Jezeli w przyszlosci chcialbym zmienic PDO na PEAR:DB to zmieniam to tylko w klasie bazowej dla modelu ... ewentualnie wyrownuje niespojnosc w API obu bibliotek piszac sobie fasade DB_Adapter ktory korzysta z PEAR:biggrin.gifB ale ma API identyczne jak PDO. Zmiana biblioteki DB odbywa sie bez naruszenia pozostalych klas i tylko w klasie bazowej dla Data Access Objects
become
aaa kumam, czyli proponujesz stworzyc klase reprezentujaca model danych usera oraz osobno klase reprezentujaco sam user.
a klasa model usera bylaby rozszerzeniem klasy bazowej model.

To ma sens jezeli zapytania sformatujesz tak jak napisales, bo np. w PDO nie ma mozliwości stworzenia zapytan tak jak w PEAR:biggrin.gifB questionmark.gif
Np. w PEAR:biggrin.gifB w zapytaniu można stosować znak zapytania, ktory zostaje zamieniony na odpowiednie wartosci z tablicy parametrów, ktorą to tablice przekazujesz do metody np. getAll.
No ale to szczegol.

A jak reprezentowac dane w klasie?

Np. jezeli mam USER'a, który w bazie SQL ma imie, nazwisko, email

To czy lepiej jest w klasie USER utworzyć jedną zmienną, która będzie przechowywać tablice zawierajacą wszystkie informacje na temat usera, czy w klasie stworzyć osbne zmienne dla imie, nazwisko, email i podstawić do nich dane z wyniku zapytania ?
NoiseMc
Ja jestem za tym zeby kazdy rekord z bazy byl reprezentowany jako obiekt z wlasciwosciami ... jakos tak bardziej mi czysto i ladnie wyglada.
Co do znakow zapytania to pewnie masz na mysli paramertyzowane zapytania ... i tak tez jest to mozliwe w PDO na dwa sposoby, wiecej tutaj: http://de2.php.net/pdo-prepare.

U mnie to wyglada tak:
  1. <?php
  2. class Products_Model extends Base_Model 
  3. {
  4. public function save (Products_Product $product)
  5. {
  6. $query = 'SELECT MAX(DisplayOrder) AS DisplayOrder FROM ' . $this->config->database->prefix . 'products LIMIT 1';
  7.  
  8. $statement = $this->db->prepare ($query);
  9. $statement->execute ();
  10.  
  11. $result = $statement->fetch ();
  12.  
  13. $maxDisplayOrder = ++$result['DisplayOrder'];
  14.  
  15. if (isset ($product->productID))
  16. {
  17. $query = 'UPDATE ' . $this->config->database->prefix . 'products SET CategoryID = ?, Name = ?, UrlSlug = ?, Copy = ?, MetaTitle = ?, MetaDescription = ?, MetaKeywords = ? WHERE ProductID = ?';
  18. }
  19. else 
  20. {
  21. $query = 'INSERT INTO ' . $this->config->database->prefix . 'products (CategoryID, Name, UrlSlug, Copy, MetaTitle, MetaDescription, MetaKeywords, 
    DisplayOrder) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
    ;
  22. }
  23.  
  24. $statement = $this->db->prepare ($query);
  25.  
  26. $statement->bindParam (1, $product->categoryID);
  27. $statement->bindParam (2, $product->name);
  28. $statement->bindParam (3, $product->urlSlug);
  29. $statement->bindParam (4, $product->copy);
  30. $statement->bindParam (5, $product->metaTitle);
  31. $statement->bindParam (6, $product->metaDescription);
  32. $statement->bindParam (7, $product->metaKeywords);
  33.  
  34. if (isset ($product->productID))
  35. {
  36. $statement->bindParam (8, $product->productID);
  37. }
  38. else 
  39. {
  40. $statement->bindParam (8, $maxDisplayOrder);
  41. }
  42.  
  43. $statement->execute ();
  44.  
  45. if (isset ($product->productID))
  46. {
  47. return $product->productID;
  48. }
  49. else 
  50. {
  51. return $this->getLastInsertID ();
  52. }
  53. }
  54. }
  55. ?>
phpion
Cytat(become @ 28.11.2007, 17:48:36 ) *
Np. w PEAR:biggrin.gifB w zapytaniu można stosować znak zapytania, ktory zostaje zamieniony na odpowiednie wartosci

Poczytaj http://pl.php.net/manual/en/ref.pdo.php w szczególności Example#7 Repeated inserts using prepared statements.

Cytat(become @ 28.11.2007, 17:48:36 ) *
A jak reprezentowac dane w klasie?

Np. jezeli mam USER'a, który w bazie SQL ma imie, nazwisko, email

To czy lepiej jest w klasie USER utworzyć jedną zmienną, która będzie przechowywać tablice zawierajacą wszystkie informacje na temat usera, czy w klasie stworzyć osbne zmienne dla imie, nazwisko, email i podstawić do nich dane z wyniku zapytania ?

Zrób tak jak napisał Ci ~NoiseMC. W klasie User opisz z czego składa się obiekt użytkownika (np. private $login, private $password itd), utwórz konstruktor, dopisz gettery i settery i w zasadzie to tyle winksmiley.jpg Natomiast w UserDb przechowuj statyczne metody pobierające dane z bazy i zwracające obiekty typu User (lub tablice obiektów).

// heh, ciut za późno no ale niech już zostanie winksmiley.jpg
NoiseMc
Wlasnie dobrze ze dodales, jeszcze gettery i settery mozna dopisac do klas Data Objects ale to jest juz zupelnie inny temat. (Przydatnosc getterow i setterow)
phpion
smile.gif

Pisanie getterów i setterów może wydawać się upierdliwe i zbędne (można przecież skorzystać z __get() oraz __set() lub po prostu określić składowe jako public winksmiley.jpg ) jednak przynosi wiele korzyści, o których poczytasz w linku podanym przez ~NoiseMC.

Od siebie dodam jeszcze, że podział modelu na User oraz UserDb jest realizowany np. przez Propel'a (komunikacja z bazą zapisana w UserPeer). Dla mnie osobiście takie rozdzielenie modelu na 2 klasy jest jak najbardziej logiczne. Masz klasę reprezentującą dany obiekt oraz klasę do manipulowania nim (Create Retrieve Update Delete).
Cysiaczek
Cytat
Od siebie dodam jeszcze, że podział modelu na User oraz UserDb jest realizowany np. przez Propel'a (komunikacja z bazą zapisana w UserPeer)


Szkoda tylko jednej rzeczy - słabej zarządzalności tą klasą. Nazwa bazy danych i tabeli zapisana na sztywno w stałej. Gdy zmianisz nazwę bazy danych, to automatycznie musisz generować model od nowa - jest to lekko irytujące podczas fazy testowej.
phpion
Cytat(Cysiaczek @ 28.11.2007, 19:30:50 ) *
Szkoda tylko jednej rzeczy - słabej zarządzalności tą klasą. Nazwa bazy danych i tabeli zapisana na sztywno w stałej. Gdy zmianisz nazwę bazy danych, to automatycznie musisz generować model od nowa - jest to lekko irytujące podczas fazy testowej.

Fakt, zgadzam się, chodziło mi tylko o rozdzielenie modelu na 2 klasy.
become
Widzać, że macie spore pojęcie o OOP. Ja dopiero zacząłem się uczyc. Dzieki za info.

Cytat(NoiseMc @ 28.11.2007, 15:08:23 ) *
Korzystam z tego tak:
  1. <?php
  2. $productsModel = new Products_Model ();
  3. $products = $productsModel->getAll ();
  4. ?>


no dobra. a czy nie lepiej byloby metody klasy Products_Model stworzyc jako statyczne i wywolywac bezposrednio
z klasy ?
  1. <?php
  2.  $products = Products_Model::getAll ();
  3. ?>


Rozumiem ze w tym przypadku model produktow stanowi wzorzec fabryki ?
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.