Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Ocena podejścia do Dependency Injection, PDO + OOP + Dependency injection
marcinq123
post
Post #1





Grupa: Zarejestrowani
Postów: 6
Pomógł: 0
Dołączył: 21.01.2013

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


Witam, uczę się OOP, zacząłem dla testów pisać klasę obsługująca bazę na podstawie PDO ( Trudno to nazwać DIC ). I proszę Was o ocenę czy w dobrą stronę to zmierza czy może podejście mam złe i później sobie skomplikuje życie ?

"Klasa DIC"

  1. class DataBaseConnection
  2. {
  3. protected $pdo;
  4. protected $mysqlHost = 'Host';
  5. protected $mysqlLogin = 'Login';
  6. protected $mysqlPassword = 'Haslo do bazy';
  7. protected $mysqlDatabase = 'Baza';
  8. public function __construct()
  9. {
  10.  
  11. try
  12. {
  13. $this->pdo = new PDO('mysql:dbname='.$this->mysqlDatabase.';host='.$this->mysqlHost.';', $this->mysqlLogin, $this->mysqlPassword);
  14. $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
  15.  
  16. }
  17. catch(PDOException $exception)
  18. {
  19. echo $exception->getMessage();
  20. }
  21. }
  22.  
  23. public function prepare($sql)
  24. {
  25. return $this->pdo->prepare($sql);
  26. }
  27.  
  28. }


Pomijając kwestię iż trzymam dane do połączenia w klasie, czy ma mniej więcej tak to wyglądać ? Ciekawi mnie dlaczego musiałem zdefiniować funkcję prepare ... jak jej nie dopiszę to wywala mi później że nie istnieje ;x

Klasa User:

  1. class User
  2. {
  3. private $login;
  4. private $query;
  5. public function __construct($baza)
  6. {
  7.  
  8. $this->pdo = $baza;
  9.  
  10. }
  11.  
  12. public function selectUser($user)
  13. {
  14. $this->login = $user;
  15.  
  16. $this->query = $this->pdo->prepare('SELECT * FROM users WHERE login =:login');
  17. $this->query->bindParam(':login', $this->login, PDO::PARAM_STR);
  18. $this->query->execute();
  19.  
  20. if($this->query->rowCount() > 0)
  21. {
  22.  
  23. $row=$this->query->fetch();
  24. $this->nazwa = $row['data'];
  25. }else{echo ' dupa ';}
  26. }
  27.  
  28.  
  29.  
  30. public function getUserData()
  31. {
  32.  
  33. return $this->nazwa;
  34.  
  35. }
  36.  
  37. }


Kod napisany tylko żeby sprawdzić czy się uruchamia.

A wywołuje metody tak:

  1. $user = new User(new DataBaseConnection());
  2.  
  3. $user->selectUser('jakisUser');
  4. echo $user->getUserData();


Ogólnie działa, no chyba że skasuje metode prepare w klasie DataBaseConnection to wtedy już nie ;p Tylko pytanie jak już wcześniej napisałem czy dobrą drogą idę ?
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
Crozin
post
Post #2





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Z Twoim kodem wszystko jest źle i nie ma to wiele wspólnego z Dependency Injection - niestety podobnie jest z późniejszymi postami w tym wątku.

1. Po co istnieje klasa DataBaseConnection skoro nie robi ona absolutnie nic poza obcięciem możliwości "surowego" PDO? Przecież możesz bezpośrednio korzystać z obiektu PDO w swoim kodzie - nie musisz tego robić przez obiekt pośredniczący.
2. Jak już, to konstruktor klasy DataBaseConnection powinien przyjąć obiekt PDO w swoim argumencie, a nie tworzyć go samemu - wtedy mielibyśmy do czynienia właśnie z DI.
3. Jeżeli nie jesteś wstanie zrobić nic z wyjątkiem, to go nie wyłapuj.
4. Musiałeś zdefiniować dla klasy DataBaseConnection metodę prepare bo dlaczego niby miałaby ona istnieć sama z siebie? Obiekt PDO udostępnia prepare(), query(), beginTransaction() i masę innych, nie DataBaseConnection.
5. W klasie User już poprawnie przekazałeś obiekt połączenia z zewnątrz. Jedynie niepotrzebnie na siłę wykorzystujesz właściwości login czy query bo tam możesz skorzystać ze zwykłych zmiennych lokalnych.

Czyli generalnie powinno to wyglądać to mniej-więcej tak:
  1. // Klasa DataBaseConnection w ogóle do kosza.
  2.  
  3. class User
  4. {
  5. private $pdo;
  6.  
  7. private $name;
  8.  
  9. public function __construct(PDO $pdo)
  10. {
  11. $this->pdo = $pdo;
  12. }
  13.  
  14. public function select($login)
  15. {
  16. $stmt = $this->pdo->prepare('SELECT ... ');
  17. $stmt->bind(..., $login);
  18. $stmt->execute();
  19.  
  20. if ($stmt->rowCount() === 0) {
  21. throw new ...Exception('...');
  22. }
  23.  
  24. $data = $stmt->fetch();
  25.  
  26. $this->name = $data['name'];
  27. }
  28.  
  29. public function getName()
  30. {
  31. return $this->name;
  32. }
  33. }
Pomijam tutaj już fakt, że wybieranie danych z bazy i ich reprezentacja w formie jednego obiektu klasy User jest bardzo złym podejściem. Powinieneś mieć raczej jeden obiekt przeznaczony do reprezentowania użytkownika (User) i drugi do wybierania takowych np. z bazy danych, czyli tzw. "model" (UserRepository).

Jeszcze co do bzdur wypisanych w postach:
1. W żadnym wypadku klasa typu user nie powinna dziedziczyć po połączeniu z bazą danych, bo: (a) nie jest takowym, ((IMG:style_emoticons/default/cool.gif) dojdzie do tego że będziesz miał otwartych po kilka połączeń na raz - kompletnie niepotrzebnie.
2. Jeżeli w jakiejś klasie potrzebujesz mieć dostęp do bazy danych to obiekt PDO powinieneś właśnie przekazać w konstruktorze.
3. Użycie Singetonu dla "klasy od bazy danych" to idiotyzm: (a) przecież może istnieć wiele równoległych połączeń do różnych baz danych((IMG:style_emoticons/default/exclamation.gif) !), ((IMG:style_emoticons/default/cool.gif) niweczysz tym wszelkie zalety płynące z IoC (DI)
4. Model nie jest synonimem operacji na bazie danych. Ta ostatnia jest w ogóle nie potrzebna. Przecież dane mogą pochodzić z dziesiątek innych źródeł, a tak w ogóle to model nie oznacza tylko wybierania danych, ale również i ich przetwarzanie.
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 12.10.2025 - 17:26