Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PostgreSQL][PHP]Tworzenie aplikacji z PDO dla kilku baz danych.
Forum PHP.pl > Forum > Przedszkole
uncuncunc
Jak tworzyć aplikacje, która będzie mogła działać na kilku bazach danych (niekoniecznie jednocześnie)? Korzystając z PDO. Tworzę zapytania SQL np. dla mysql, jednak te mogą się różnić w wypadku posgresql, więc jak to rozdzielić? Przecież nie będę tworzył osobnych paczek/plików dla konkretnej bazy. Zrobić to na klasach? Tylko że tworzenie klasy, do obsługi PDO jest chybione... Jak rozwiązujecie te kwestie u siebie?
Crozin
http://nl3.php.net/manual/en/intro.pdo.php - drugi akapit już Cię informuje, że PDO nie ingeruje w żaden sposób w treść Twoich zapytań.

Możesz:
1. Skorzystać z jakiejś warstwy abstrakcji nad samą bazą danych - co i tak pewnie robisz korzystając z ORM-a (np. Doctrine).
2. Stworzyć osobną implementację dla każdego silnika bazy danych, tj.: a) Utworzyć paczkę z interfejsami (MyProject\DAO) oraz paczkę z implemetacją dla każdej z bazy danych (MyProject\DAO\Impl\MySQL, MyProject\DAO\Impl\PostgreSQL), cool.gif W całym projekcie oczywiście nie powinno być absolutnie żadnego nawiązania do którejkolwiek z paczek implementacji (poza konfiguracją).

PS. I oczywiście żadna z klas nie będzie tutaj obsługiwać PDO samego w sobie - będzie natomiast z niego korzystać.
uncuncunc
  1.  
  2. $db = new dbconnect('mysql'); // ustalam jaki typ bazy (wartosc odczytana np. z CFG), choć domyślnie może być to posgresql
  3. $db->pdo-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // wysyłam dodatkowe atrybuty
  4.  
  5. if($db-> is_db('posgresql')) // sprawdzam czy baza to posgresql
  6. {
  7. $getCokolwiek = $db->pdo-> prepare('SELECT cos FROM `gdzies` WHERE tu_lag =:lang LIMIT 1');
  8. }
  9. elseif($db-> is_db('mssql)') // czy mssql
  10. {
  11. $getCokolwiek = $db->pdo-> prepare('SELECT cos FROM `gdzies` WHERE tu_lag =:lang LIMIT 1');
  12. }
  13. else // ewentualnie wszytko inne
  14. {
  15. $getCokolwiek = $db->pdo-> prepare('SELECT cos FROM `gdzies` WHERE tu_lag =:lang LIMIT 1');
  16. }
  17.  
  18. $getCokolwiek -> bindValue(':lang', 'pl_pl', PDO::PARAM_STR)
  19. $getCokolwiek -> execute();


Czy takie podejście byłoby dobre, biorąc pod uwagę że byłoby wykonywane w modelu (MVC)?
Crozin
Cytat
tj.: a) Utworzyć paczkę z interfejsami (MyProject\DAO) oraz paczkę z implemetacją dla każdej z bazy danych (MyProject\DAO\Impl\MySQL, MyProject\DAO\Impl\PostgreSQL)
Nawet nie próbuj tego robić w taki sposób jak zaproponowałeś bo się umęczysz z tym.
uncuncunc
Aha, czyli to powinno wyglądać mniej więcej tak:

  1. $db = new dbconnect(); // tu zostaje wczytany z cfg jaka ma być baza
  2. $db-> select('cos', 'gdzies', 'tu_lang') // odpowiednik 'SELECT cos FROM `gdzies` WHERE tu_lag =:lang LIMIT 1'


O to Ci chodzi?
Crozin
Za zwracanie danych (obiektów) ze źródła danych (np. bazy danych) odpowiedzialne są obiekty DAO. Dla każdego typu danych i każdego źródła danych powinieneś mieć osobny obiekt. Każde źródło danych może pobierać dane w sobie tylko znany sposób, ale powinno zapewniać wspólny dla wszystkich źródeł interfejs - dzięki temu w aplikacji będziesz mógł transparentnie korzystać z dowolnego źródła.
  1. interface SomethingDao {
  2. public function findByLanguage($language);
  3. }
  4.  
  5. class MysqlSomethingDao {
  6. public function findByLanguage(...) {
  7. // ... zwraca dane w sposób specyficzny dla MySQL-a
  8. }
  9. }
  10.  
  11. class PostgresSomethingDao {
  12. public function findByLanguage(...) {
  13. // ... zwraca dane w sposób specyficzny dla Postgresa
  14. }
  15. }
  16.  
  17. class FacebookSomethingDao {
  18. public function findByLanguage(...) {
  19. // ... zwraca dane w sposób specyficzny dla Facebookowego webservice'a
  20. }
  21. }
  22.  
  23. // A w samej aplikacji masz co najwyżej:
  24.  
  25. public function doSomething(SomethingDao $sthDao) {
  26. $sth = $sthDao->findByLanguage('en');
  27. $sth->doSthElse();
  28. }
uncuncunc
Czytam właśnie o tym, przegląda różne bazy i sposoby... i rozumiem samą ideę, jednak... To jest tylko nadbudówka, co nie wydaje mi się zbyt korzystne, bo muszę sam pisać interfejs, to tak jakbym chciał zrobić obsługę połączeń z bazami, gdy nie było PDO. Chociaż jakby się nad tym zastanowić, to coś w tym może być, a są jakieś spójne interfejsy lub nazewnictwo? Albo coś 'natywnego' w php? I jak nazywa się to:

Kod
public function doSomething(SomethingDao $sthDao) {


Chodzi mi o wywołanie klasy w metodzie, bo chce o tym poczytać.
Crozin
Interfejsy DAO deklarują metody wykonujące operacje odczytu/zapisu danych biznesowych ze/do źródła danych, zaś samo PDO deklaruje metody pozwalające na połączenie aplikacji ze źródłem danych (w dodatu bardzo konkretnym), tak więc to nie do końca to samo. wink.gif
Cytat
[...] a są jakieś spójne interfejsy lub nazewnictwo?
Nie ma jakiś konkretnych wytycznych co do nazewnictwa. Z reguły interfejsy będą kończyły się przyrostkiem Dao/DAO (na sposób zapisu akronimów też nie ma jednoznacznej konwencji), a implementacje będą znajdować się w osobnej paczce (np. interfejsy w My\Project\Dao, a implementacje w My\Project\Dao\Impl\[Mysql|Postgres|Oracle|Mssql]).

Cytat
I jak nazywa się to:
Kod
public function doSomething(SomethingDao $sthDao) {

Chodzi mi o wywołanie klasy w metodzie, bo chce o tym poczytać.
Ale tu jest tylko zadeklarowana metoda doSomething() z jednym argumentem, który musi być obiektem implementującym interfejs SomethingDao. Jeżeli o to Ci chodzi to nazywa się to type hinting.

Swoją drogą, z racji na to, że w większości SQL-owskich baz danych zapytania są niemal identyczne (mowa oczywiście o prostych operacjach), będziesz mógł utworzyć sobie jeden obiekt (dla każdego rodzaju danych), po którym mogłyby dziedziczyć implementacje specyficznych baz danych:
  1. namepsace My\Project\Dao;
  2.  
  3. interface UserAccountDao {
  4. public function findInactive();
  5. public function activate(Account $account);
  6. }
  7.  
  8. namespace My\Project\Dao\Impl;
  9.  
  10. abstract class AbstractUserAccountDao {
  11. protected $conn;
  12.  
  13. public function __construct(\PDO $conn) {
  14. $this->conn = $conn;
  15. }
  16.  
  17. public function findInactive() {
  18. $sql = $this->getFindInactiveQuery();
  19.  
  20. $stmt = $this->conn->prepare($sql);
  21. $stmt->execute();
  22.  
  23. return $stmt->findAll();
  24. }
  25.  
  26. public function activate(Account $account) {
  27. $sql = $this->getActivateQuery();
  28.  
  29. $stmt = $this->conn->prepare($sql);
  30. $stmt->bindValue('id', $account->getId(), \PDO::PARAM_INT);
  31. $stmt->execute();
  32. }
  33.  
  34. protected function getFindInactiveQuery() {
  35. return 'SELECT ... FROM ... WHERE is_active = 0 ...;';
  36. }
  37.  
  38. protected function getActivateQuery() {
  39. return 'UPDATE ... SET is_active = 1 WHERE id = :id;';
  40. }
  41. }
  42.  
  43. namespace My\Project\Dao\Impl\Mysql;
  44.  
  45. class UserAccountDao extends AbstractUserAccountDao { }
  46.  
  47. namespace My\Project\Dao\Impl\Postgres;
  48.  
  49. class UserAccountDao extends AbstractUserAccountDao {
  50. protected function getFindInactiveQuery() {
  51. return 'jakieś tam specyficzne dla postgresa zapytanie - tutaj notabene nie potrzebne';
  52. }
  53. }
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.