Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP] singleton a trzy bazy danych
patryczakowy
post
Post #1





Grupa: Zarejestrowani
Postów: 420
Pomógł: 44
Dołączył: 22.10.2008

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


Witam mam mały problem mam skrypt który korzysta z trzech baz danych założenie było takie żeby podczas wykonywania skryptu były maksymalnie trzy połączenia z bazą dlatego chciałem zimplementować wzorzec singleton dl a każdej z baz jednak problem jest taki że podczas wywołania klasy z połączeniem do drugiej bazy połączenie z pierwszą zostaje przerwane po niżej przykładowy kody
  1. class db_portal extends db{
  2.  
  3.  
  4. private function __construct() {
  5. $cfg['db']['host']='localhost';
  6. $cfg['db']['user']='xxxxxx';
  7. $cfg['db']['password']='xxxxx';
  8. $cfg['db']['name']='xxxxxx';
  9. $this->conn_id = mysql_connect($cfg['db']['host'],$cfg['db']['user'],$cfg['db']['password']);
  10. mysql_select_db($cfg['db']['name'],$this->conn_id);
  11. mysql_query("SET CHARACTER SET utf8");
  12. mysql_query("SET collation_connection = utf8_unicode_ci");
  13. if(! is_resource($this->conn_id)) {
  14. return false;
  15. }
  16. }
  17. static public function connect_db () {
  18. static $objDB;
  19. if(!isset($objDB))
  20. $objDB = new db_portal;
  21.  
  22. return $objDB;
  23. }
  24. }
  25. class db_portal2 extends db{
  26.  
  27.  
  28. private function __construct() {
  29. $cfg['db']['host']='localhost';
  30. $cfg['db']['user']='xxxxxx';
  31. $cfg['db']['password']='xxxxx';
  32. $cfg['db']['name']='xxxxxx';
  33. $this->conn_id = mysql_connect($cfg['db']['host'],$cfg['db']['user'],$cfg['db']['password']);
  34. mysql_select_db($cfg['db']['name'],$this->conn_id);
  35. mysql_query("SET CHARACTER SET utf8");
  36. mysql_query("SET collation_connection = utf8_unicode_ci");
  37. if(! is_resource($this->conn_id)) {
  38. return false;
  39. }
  40. }
  41. static public function connect_db () {
  42. static $objDB;
  43. if(!isset($objDB))
  44. $objDB = new db_portal2;
  45.  
  46. return $objDB;
  47. }
  48. }
  49. $DB=db_portal::connect_db();
  50. //zapytania z bazy 1
  51. $DB2=db_portal2::connect_db();
  52. // zapytania z bazy 2
  53. $DB->query($SQL);
  54. //problem objekt $DB istnieje ale niema już połączenia z bazą przez co zapytanie się nie wykonuje
  55. //nie pomaga nawet dodanie linii wcześniej $DB=db_portal::connect_db();

Klasa db to standardowa klasa mająca metody typu query fetch itp

Ma ktoś pomysł jak można to rozwiązaćquestionmark.gif?

Z góry dzięki za sugestie.

Ten post edytował patryczakowy 22.01.2011, 08:07:27


--------------------
Sztuką jest widzieć to czego nie widać.
Go to the top of the page
+Quote Post
Smertius
post
Post #2





Grupa: Zarejestrowani
Postów: 156
Pomógł: 31
Dołączył: 23.02.2009
Skąd: Sanok

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


Wg mnie powinieneś łączenie z bazą danych przenieść do konstruktora bazy DB, a w klasach które po niej dziedziczą wywoływać konstruktor rodzica przez parent::__construct(), nie ma sensu tego pchać do każdej klasy w dodatku jeśli będziesz chciał zmienić dane do BD to bedziesz to zmieniał w N klasach? Trochę to niewygodne.

Co do Singeltona, to błędnie go implementujesz. Rzuć okiem na kod:

  1. class klasa {
  2.  
  3. private static $instance;
  4.  
  5. public function __construct() {
  6. if (!(self::$instance instanceof klasa)) {
  7. self::$instance = $this;
  8. return self::$instance;
  9. } else {
  10. return self::$instance;
  11. }
  12. }
  13. }


Tak jak powyżej, jeśli po pierwszym utworzeniu obiektu "klasa", spróbujesz go utworzyć jeszcze raz (new Klasa) to zostanie zwrócony już istniejąca instancja "klasa"

IMHO mamy PDO, mamy ORM a ludzie dalej korzystają z niewygodych, przestarzałych funkcji typu mysql_query itp. ...
Go to the top of the page
+Quote Post
Mephistofeles
post
Post #3





Grupa: Zarejestrowani
Postów: 1 182
Pomógł: 115
Dołączył: 4.03.2009
Skąd: Myszków

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


Użyj np. Doctrine DBAL (czy nawet całego ORMa), załatwi sprawę kilku połączeń. Albo po prostu PDO. Mysql_ było dobre może 5 lat temu, nie pamiętam kiedy wszedł PHP 5 z PDO.
Go to the top of the page
+Quote Post
Crozin
post
Post #4





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

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


@Smertius: Proponuje Ci sprawdzać swój kod przed podaniem, bo kompletne bzdury wypisujesz...
Go to the top of the page
+Quote Post
Smertius
post
Post #5





Grupa: Zarejestrowani
Postów: 156
Pomógł: 31
Dołączył: 23.02.2009
Skąd: Sanok

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


Tzn?
Go to the top of the page
+Quote Post
patryczakowy
post
Post #6





Grupa: Zarejestrowani
Postów: 420
Pomógł: 44
Dołączył: 22.10.2008

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


Cytat(Smertius @ 22.01.2011, 10:00:59 ) *
(..) nie ma sensu tego pchać do każdej klasy w dodatku jeśli będziesz chciał zmienić dane do BD to bedziesz to zmieniał w N klasach? Trochę to niewygodne.

Tak w N klasach bo mam N baz danych smile.gif
Cytat(Smertius @ 22.01.2011, 10:00:59 ) *
Co do Singeltona, to błędnie go implementujesz. Rzuć okiem na kod:

Co do implementacji wzorca singleton to zaczerpnełem go z tej książki
Cytat(Smertius @ 22.01.2011, 10:00:59 ) *
Tak jak powyżej, jeśli po pierwszym utworzeniu obiektu "klasa", spróbujesz go utworzyć jeszcze raz (new Klasa) to zostanie zwrócony już istniejąca instancja "klasa"

IMHO mamy PDO, mamy ORM a ludzie dalej korzystają z niewygodych, przestarzałych funkcji typu mysql_query itp. ...


i tak samo działa moja klasa objekt jest ale nie mam już połączenia z bazą danych gdyż wcześniej zainicjowałem połączenie z drugą bazą danych
Cytat
Użyj np. Doctrine DBAL (czy nawet całego ORMa), załatwi sprawę kilku połączeń. Albo po prostu PDO. Mysql_ było dobre może 5 lat temu, nie pamiętam kiedy wszedł PHP 5 z PDO.

Wygodne nie wygodne jak się ma masę kodu do przerobienia to się kombinuje tak żeby wszystkiego nie trzeba było pisać od początku, a było w miarę optymalne jeśli zainicjuje trzy połączenia do trzech różnych baz danych przy pomocy PDO to te trzy połączenia będą istnieć cały czas równolegle questionmark.gif? i co w takim razie ze wszystkimi zwykłymi zapytaniami mysql_query które już istnieją bo w obecnym momencie do póki nie inicjowałem drugiej klasy to po wywołaniu
  1. $DB=db_portal::connect_db();

jeśli w kodzie gdzieś dalej istniało coś takiego
  1. $a= mysql_query("SELECT * FROM TABELA");
  2.  


to wszystko działało bez konieczności ingerencji w już napisany kod


--------------------
Sztuką jest widzieć to czego nie widać.
Go to the top of the page
+Quote Post
Fifi209
post
Post #7





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

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


A do manuala nie łaska zajrzeć?

Cytat
resource mysql_connect ([ string $serwer = ini_get("mysql.default_host") [, string $nazwa_użytkownika = ini_get("mysql.default_user") [, string $hasło = ini_get("mysql.default_password") [, bool $nowe_połączenie = false [, int $flagi_klienta = 0 ]]]]] )




--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
patryczakowy
post
Post #8





Grupa: Zarejestrowani
Postów: 420
Pomógł: 44
Dołączył: 22.10.2008

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


Cytat(fifi209 @ 22.01.2011, 12:47:20 ) *
A do manuala nie łaska zajrzeć?

sorki ale może nie zawsze umiem wyciągnąć z manula to co mi potrzebne, niezabardzo wiem z jakimi parametrami mam wywołać to mysql_connect aby działało tak jak ja chcę mysql_connect , nawet jeślim dam tak
  1. $this->conn_id = mysql_connect($cfg['db']['host'],$cfg['db']['user'],$cfg['db']['password'],true);

to nie działa, czemu zresztą się nie dziwię gdyż przy drugim wywołaniu objekt istnieje więc konstruktor nie jest wywoływany, z resztą takie było założenie żeby z bazą łączyć się tylko raz

chyba coś przekombinowałem powoli zaczyna dochodzić do mnie że bez przepisania wszystkiego pożądanego efektu nie osiągnę niemniej jednak czekam na jakieś koło ratunkowe


--------------------
Sztuką jest widzieć to czego nie widać.
Go to the top of the page
+Quote Post
Crozin
post
Post #9





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

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


1. mysql_query powinno mieć określone z którego połączenia korzysta (patrz drugi argument funkcji).
2. Przestań korzystać z Singletona, bo na stronach WWW jest naprawdę baaaaardzo niewiele sytuacji, gdzie jego użycie miałoby sens, a korzystanie z tego wzorca poza jedną zaletą (powodem, dla którego stworzono go - czyli zapewnieniem istnienia co najwyżej jeden instancji danej klasy) ciągnie za sobą masę problemów.
3. Zapewne korzystasz z Singletona by uzyskać globalny dostęp do bazy danych (to jest złe użycie oczywiście), ale mógłbyś wykorzystać coś takiego:
  1. // Zakładam, że klasa DB to mniej-więcej coś takiego:
  2.  
  3. class DB {
  4. protected $connection;
  5.  
  6. public function __construct($host, ...) {
  7. $this->connection = mysql_connect(...);
  8. }
  9.  
  10. public function query($sql) {
  11. $result = mysql_query($sql, $this->connection);
  12. }
  13.  
  14. // etc.
  15. }
  16.  
  17. // Tak więc utwórzmy sobie najpierw jakiegoś globalnego (złe, ale skoro tak już musisz mieć) menadżera połączeń:
  18. class DBManager {
  19. protected static $connections = array();
  20.  
  21. public static function get($name) {
  22. return self::$connections[$name];
  23. }
  24.  
  25. public static function set($name, DB $connection) {
  26. self::$connections[$name] = $connection;
  27. }
  28. }
  29.  
  30. // W którymś tam miejscu skryptu inicjalizujesz połączenia:
  31.  
  32. $defaultConnection = new DB('...', '...');
  33. $extraConnection = new DB('....');
  34. $yetAnotherConnection = new DB(...);
  35.  
  36. // I dodajesz je do menadżera:
  37.  
  38. DBManager::set('default', $defaultConnection);
  39. DBManager::set('extra', $extraConnection);
  40. DBManager::set('yetAnothert', $yetAnotherConnection);
  41.  
  42. // Teraz w dowolnej części aplikacji możesz zrobić coś w stylu:
  43.  
  44. $db = DBManager::get('extra');
  45. $db->query('...');
  46.  
  47. $db = DBManager::get('default');
  48. $db->fetchArray('....');


Cytat
Tzn?
To znaczy, że to co podałeś nie jest Singletonem. To papka bezsensownego kodu (konstruktor zwracający coś? wtf?!)
Go to the top of the page
+Quote Post
patryczakowy
post
Post #10





Grupa: Zarejestrowani
Postów: 420
Pomógł: 44
Dołączył: 22.10.2008

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


To co podałeś rozwiązało prawie cały problem i wielkie dzięki, jednak tak jak pisałem wcześniej niestety wiąże się to z przepisaniem wszystkich wystąpień mysql_query, a chciałem tego uniknąć jak widać nie da rady, ale może to i lepiej przy okazji przejże wszystkie zapytania do bazy smile.gif


--------------------
Sztuką jest widzieć to czego nie widać.
Go to the top of the page
+Quote Post
Crozin
post
Post #11





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

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


Jeżeli i tak jesteś zmuszony przepisać zapytania to skorzystaj z PDO, które mimo iż nie idealne jest znacznie lepszym interfejsem niż funkcje mysql_*().
Go to the top of the page
+Quote Post

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: 22.08.2025 - 03:11