Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Klasa singleton do obsługi DB
Forum PHP.pl > Forum > Przedszkole
-derwu-
Witajcie,

stworzyłem klasę singleton służącą do obsługi bazy danych (aplikacja będzie korzystać tylko z jednej bazy danych). Konstruktor klasy przyjmuje argumenty takie jak adres serwera, login, hasło do DB.

Mam drugą klasę, która potrzebuje korzystać z bazy danych. Mam pytanie jak rozwiązać kwestię tworzenia obiektu klasy singleton, bo przecież nie tworzy się tutaj obiektu klasy "bezpośrednio", lecz za pomocą innej funkcji. Aktualnie zrobiłem to tak, że w klasie obsługującej bazę danych, w funkcji tworzącej/zwracającej obiekt tejże klasy, dodałem argumenty te same co w konstruktorze:
  1. private function __construct($server, $username, $password, $database)
  2. {
  3. // tutaj jakieś operacje
  4. }
  5. public static function singleton($server = NULL, $username = NULL, $password = NULL, $database = NULL)
  6. {
  7. if (!isset(self::$instance)) {
  8. $className = __CLASS__;
  9. self::$instance = new $className($server, $username, $password, $database);
  10. }
  11. return self::$instance;
  12. }

Gdzieś tam np. w index.php tworzę sobie obiekt klasy obsługującej bazę danych:
  1. $DB = BazaDanych::singleton($server, $username, $password, $database);

W tym wypadku w drugiej klasie, wykorzystującej bazę danych, mam referencję do wcześniej utworzonego obiektu klasy obsługującej bazę danych:
  1.  
  2. private $DB;
  3.  
  4. public function __construct(){
  5. $this->DB = BazaDanych::singleton()
  6. }

Wszystko działa, ale nie jestem pewien czy dobrze to zorganizowałem. Nie wygląda to sensownie...
bastard13
Osobiście uważam, że nie jest Ci potrzebny tutaj singleton. Obsługę baz danych naprawdę da się zrealizować bez jego implementacji, a to, że teraz korzystasz z jednej bazy to też nie jest dobry argument, bo w przyszłości może być potrzeba zainicjowania kolejnego połączenia lub będziesz miał stworzyć nową aplikację, która wykorzystuje n baz danych. I wtedy Twój obecny kod będzie nie przydatny.
To tyle w kwestii moralizowania:P A co do odpowiedzi na twoje pytanie, to można to zrobić w ten sposób:
  1. class DbConnection
  2. {
  3. private static $_instance = null;
  4. private $_connectionData; //dane niezbędne do połączenia, to jak je przedstawisz (tablica lub rozbicie na osobne atrybuty) jest nieistotne.
  5. private $_connection = null; //połączenie z bazą danych
  6.  
  7. public static function getInstance()
  8. {
  9. if (self::$_instance === null)
  10. self::$_instance = new self;
  11.  
  12. return self::$_instance;
  13. }
  14. public function isConnected() { return $this->_connection !== null; }
  15. public function connect($server, $username, $password, $database) { /*łączenie się z bazą*/ }
  16. private function __construct();
  17. private function __clone();
  18. }


Dzięki temu oddzielasz pobieranie instancji obiektu od inicjowania połączenia. Do metody connect() możesz dodać kod, który rzuca wyjątkiem, jeżeli jest już połączenie.

A przypisywanie instancji singletona do atrybutu klasy (Twoja druga klasa), jest naprawdę zbędne skoro już implementujesz singleton. W takim wypadku DbConnection zamieniłbym na normalną klasę i użyłbym DI do przekazania go do tej klasy.
mortus
Być może singleton nie jest tutaj potrzebny i rzeczywiście taka implementacja singletona nie przyda się w sytuacji, gdy będziemy chcieli uzyskać dostęp do kilku baz danych. Warto jednak wiedzieć, że można zaimplementować wzorzec singleton tak, żeby obsługiwał nam te nasze n połączeń z bazą danych. Oczywiście ma to pewne ograniczenia, bo musimy określić maksymalną liczbę połączeń. W każdym bądź razie chciałem zwrócić uwagę, że klasa singleton nie zawsze musi służyć do tworzenia i obsługi dokładnie jednej instancji obiektu tej klasy, choć przeważnie do tego służy.
Derwu
Cytat(bastard13 @ 23.11.2011, 14:56:37 ) *
(...) A przypisywanie instancji singletona do atrybutu klasy (Twoja druga klasa), jest naprawdę zbędne skoro już implementujesz singleton. (...)


A jak inaczej w tym przypadku, uzyskać dostęp do obiektu klasy DB który jest singletonem (pomijając przekazywanie jako argument)?
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.