![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Piszę sobie klasę do obsługi bazy danych i przyglądam się tak bardzo popularnemu wzorcowi singleton. Wszyscy jako przykład użyteczności tego wzorca podają przykład tworzenia instancji klasy do obsługi bazy, tzn połączenia z bazą. Zacząłem się zastanawiać gdzie jest sens, oczywiście w języku php. Zakładam, że mam taką klasę i w skrypcie łącze się z bazą danych, jeśli nie ma nawiązanego połączenia to tworzę obiekt tej klasy a jeśli jest to nie tworzę.
Wszystko jasne. Tylko gdzie jest sens stosowania tego w php. Przecież w skrypcie zazwyczaj tworzy się połączenie z bazą, wykonuje potrzebne operacje na bazie a po zakończeniu wywoływania skryptu, połączenie i tak jest zamykane automatycznie.. Więc jaki jest sens stosowania tego w php? |
|
|
![]()
Post
#2
|
|
Grupa: Przyjaciele php.pl Postów: 5 724 Pomógł: 259 Dołączył: 13.04.2004 Skąd: N/A Ostrzeżenie: (0%) ![]() ![]() |
To nie chodzi o to masz obiekt polaczenia dostepny miedzy kolejnymi wykonaniami skrytpu, tylko gdy potrzebujesz w wyswietleni jednej strony w kilku miejscach wykonac zapytania do bazy to masz opcje:
- wszedie pisac (np.) mysql_connect(...) - ciagle przekazywac w argumentach funckji raz utworzony obiekt polaczenia - uzyc singletona -- wystarczy DB::getInstance() i masz polaczenie, z kazdego poziomu zagniezdzenia funkcji, bez koniecznosci podawani paranetrow polaczenia - uzyc rejestru, tworzysz obiekt DB, wrzucasz go do rejestru (ktory moze przechowywac mnostwo innych wszedzie-potrzebnych-obiektow), i pobierasz gdy potrzebujesz; od singletona rozni sie tym ze mozesz wymienic polaczenie na inne; jest bardziej OOP gdyz singleton to taki obiekt globalny, a przeciez globale sa BE (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Przecież można raz wywołać mysql_connect a zwrócone uchwyt przypisać do zmiennej statycznej.. Wtedy nie trzeba drugi raz tworzyć połączenia. Ale czy to nie będzie mało OOP?
|
|
|
![]()
Post
#4
|
|
Grupa: Moderatorzy Postów: 4 465 Pomógł: 137 Dołączył: 26.03.2004 Skąd: Gorzów Wlkp. ![]() |
Tak, ale bardzo często w bardziej rozbudowanych aplikacjach odwołanie do obiektu DB jest przezroczyste, tzn, że nie podajesz konkretnego połączenia, tylko "prosisz" warstwę danych o konkretne rekordy z konkretnych tabel. Ba! Nie interesuje Cię nawet, z jaką bazą masz do czynienia. Twoja warstwa danych z kolei jak nie znajdzie bazy danych, lub nie zdoła się połączyć, może pobrać dane z pliku .txt, lub .xml. Zaloguje przy tym kto i w jaki sposób dobierał się do danych. Teraz przy tak skomplikowanym systemie spróbuj używać wszędzie DB::query($sql, "mysql") itp. Połączeń zresztą może być wiele (różne bazy danych np.). Trzeba je upchać zatem w tablicę... a może lepiej stworzyć kolekcję obiektów połączenia? Jak to zrobisz na korzystając ze składowych statycznych? Możliwości są setki, a użycie statycznej składowej to rozwiązanie najmniej skomplikowane.
Pozdrawiam. |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Tak, ale bardzo często w bardziej rozbudowanych aplikacjach odwołanie do obiektu DB jest przezroczyste, tzn, że nie podajesz konkretnego połączenia, tylko "prosisz" warstwę danych o konkretne rekordy z konkretnych tabel. No ale gdzieś musi być wskazane z jakiego połączenia chcesz skorzystać, bo w przeciwnym przypadku można się przejechać (np w skrypcie gdzieś po drodze nastąpiło połączenie z inną bazą i wtedy zostanie użyte ostatnie nawiązane połączenie, a my chcemy inne). Teraz przy tak skomplikowanym systemie spróbuj używać wszędzie DB::query($sql, "mysql") Typ bazy mam zapisany w pliku konfiguracyjnym i w nim zmieniam tyb bazy z której chcę korzystać. Nie widzę też problemu, żeby do pobrania wyników korzystać z $oDatabase->query($handle, $query). Przecież to nic złego. itp. Połączeń zresztą może być wiele (różne bazy danych np.). Trzeba je upchać zatem w tablicę... a może lepiej stworzyć kolekcję obiektów połączenia? Jak to zrobisz na korzystając ze składowych statycznych? Możliwości są setki, a użycie statycznej składowej to rozwiązanie najmniej skomplikowane. Z tą zmienną statyczną to chodziło mi o to, że zamiast pisać całego singletona definiujesz tylko zmienną statyczną i jej przypisujesz uchwyt połączenia. I zamiast pisać kilka linijek singletona piszesz jeden warunek, oraz możesz używać konstruktora do sprawdzania parametrów.. |
|
|
![]()
Post
#6
|
|
Grupa: Moderatorzy Postów: 4 465 Pomógł: 137 Dołączył: 26.03.2004 Skąd: Gorzów Wlkp. ![]() |
Ale nie o to chodzi w Singletonie. To jest wzorzec do rozprowadzania i udostępniania tego samego obiektu wielu innym klasom i obiektom. To, że wiele osób zaleca go do udostępniania obiektu DB, to nie znaczy, że nie można stosować alternatywnych rozwiązań. Jeśli chcesz udostępniać tylko wskaźnik połączenia, to nie musisz robić do tego singletona. Możesz tak jak mówisz zrobić static $zmienna, albo wogóle global $zmienna. Wartości Singletona nie zobaczysz w małym skrypcie, albo w systemie www pisanym strona po stronie. Zobaczysz za to w bardzo rozproszonej, polimorficznej aplikacji, gdzie 20 klas operuje na jednym i tym samym obiekcie (np mapa pliku konfiguracyjnego) wierząc, że nie może być inaczej, bo gdyby było - system by padł.
Najważniejsza jest zasada: Nie będziesz tego potrzebował oraz Jeśli nie widzisz problemu, nie korzystaj ze wzorca na siłę Pozdrawiam. |
|
|
![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Jeśli chcesz udostępniać tylko wskaźnik połączenia, to nie musisz robić do tego singletona. A co innego udostępnia singleton? Przecież chodzi właśnie o uchwyt połączenia.. Nigdy nie stosuję czegoś na siłę. Pytam się bo chcę rozważyć na ile może być to przydatne. |
|
|
![]()
Post
#8
|
|
Grupa: Przyjaciele php.pl Postów: 1 224 Pomógł: 40 Dołączył: 6.07.2004 Skąd: Wuppertal Ostrzeżenie: (0%) ![]() ![]() |
Singleton pozwala Ci uzyskać dostęp do obiektu w kazdym miejscu Twojej aplikacji. Nie wazne czy to uchwyt bazy danych, czy obiekt config czy cokolwiek co sobie wymyślisz.
Jeśli chcesz zrobić obiektową otoczkę Twojego korzystania z bazy danych najlepiej narysuj sobie schemat jaki obiekt ma za co odpowiadać. Ja generalnie stosowałem 3 obiekty. 1. DB_Connection - to był obiekt oparty właśnie o singleton, wewnątrz niego trzymałem uchwyt do db. Były tez tam 'logi' zapytań i inne pierdoły. 2. DB_Query - obiekt zapytania. Robiłem wtedy tak:
3. DB_Result - to co zwróciła funkcja execute, w zaleznosci od zapytania wiersze albo inne bajery. Singletona uzywalem w tym przypadku po to zeby mieć łatwy dostęp do połączenia z bazą. Dochodzi jeszcze kolejna kwestia, czy będziesz uzywać kilku baz danych na raz? bo jeśli tak - ja założyłem ze nie będę - to musisz inaczej zaprojektować swój system np.
Do tego powinienneś przemyśleć dodatkowo czy będziesz korzystał tylko z baz typu mysql? Jeśli nie wtedy DB_Connection powinno być interfejsem, a implementować i używać powinienneś DB_Connection_Mysql, DB_Connection_Pgsql itd... Jest bardzo duzo zależności, musisz sam wszystko przemyśleć, a wzorce to tylko sposób implementacji. Radze Ci lepiej zacznij od poznania problemu, a dopiero potem szukaj rozwiązania. Bo tutaj pytasz o pewien sposób użycia singletonu, a nie do końca jestem pewny czy wiesz do czego chcesz go użyć. |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Jeśli chcesz zrobić obiektową otoczkę Twojego korzystania z bazy danych najlepiej narysuj sobie schemat jaki obiekt ma za co odpowiadać. Ja generalnie stosowałem 3 obiekty. 1. DB_Connection - to był obiekt oparty właśnie o singleton, wewnątrz niego trzymałem uchwyt do db. Były tez tam 'logi' zapytań i inne pierdoły. 2. DB_Query - obiekt zapytania. Robiłem wtedy tak:
3. DB_Result - to co zwróciła funkcja execute, w zaleznosci od zapytania wiersze albo inne bajery. Singletona uzywalem w tym przypadku po to zeby mieć łatwy dostęp do połączenia z bazą. Moim zdaniem niepotrzebnie rozbijałeś to na 3 obiekty. Ja chcę zamknąć wszystko w jednej klasie. Dochodzi jeszcze kolejna kwestia, czy będziesz uzywać kilku baz danych na raz? bo jeśli tak - ja założyłem ze nie będę - to musisz inaczej zaprojektować swój system np.
Do tego powinienneś przemyśleć dodatkowo czy będziesz korzystał tylko z baz typu mysql? Jeśli nie wtedy DB_Connection powinno być interfejsem, a implementować i używać powinienneś DB_Connection_Mysql, DB_Connection_Pgsql itd... Ja wymyśliłem to trochę w inny sposób. Najwyżej podczas testów klasy stwierdzę, że trzeba coś zmienić. Mam interfejs który zawiera wymagane metody. Teraz każda klasa (osobna dla każdego rodzaju bazy) implementuje ten interfejs. W pliku konfiguracyjnym mam zapisane z jakiej bazy korzystam i na podstawie tego zapisu będzie wykorzystywana odpowiednia klasa do połączenia. Ale zacząłem się zastanawiać czy nie będę chciał korzystać z kilku różnych baz, np w jednej aplikacji pobierać dane z bazy pgsql na serwerze xxx.xxx.xxx.xxx i zapisywać w bazie mysql na localhost (to tylko przykład).. To mój sposób z plikiem konfiguracyjnym nie jest za dobry. Oczywiście można by w pliku konfiguracyjnym definiować konfiguracje dla dwóch baz, ale co jeśli będę chciał korzystać z 10 różnych (hardcorowy przykład ale staram się nie ograniczać).. Jeszcze się nad tym zastanowię. Ale tutaj całkiem rozsądne jak nie jedyne słuszne rozwiązanie to wzorzec registry. Jest bardzo duzo zależności, musisz sam wszystko przemyśleć, a wzorce to tylko sposób implementacji. Radze Ci lepiej zacznij od poznania problemu, a dopiero potem szukaj rozwiązania. Bo tutaj pytasz o pewien sposób użycia singletonu, a nie do końca jestem pewny czy wiesz do czego chcesz go użyć. Już się nad tym zastanawiałem i wiem co chcę osiągnąć. Natomiast pytam się o singletona bo wbrew opiniom innym nie widzę sensu stosowania go w php. CHYBA, że w jednym skrypcie (pojedynczym bo nie ma co ukrywać ale każda aplikacja w php to kolejne skrypty) korzystamy z kilku różnych baz - wtedy moim zdaniem singleton się sprawdzi. Ale jeśli korzystamy tylko z jednej bazy, to stosowanie singletona moim zdaniem jest przerostem formy nad treścią. |
|
|
![]()
Post
#10
|
|
Grupa: Przyjaciele php.pl Postów: 1 224 Pomógł: 40 Dołączył: 6.07.2004 Skąd: Wuppertal Ostrzeżenie: (0%) ![]() ![]() |
mozesz przedstawic interfejs swoich przemyśleń?
|
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
|
|
|
![]()
Post
#12
|
|
Grupa: Przyjaciele php.pl Postów: 1 224 Pomógł: 40 Dołączył: 6.07.2004 Skąd: Wuppertal Ostrzeżenie: (0%) ![]() ![]() |
a mozesz w jakis sposob przedstawic Twoje przemyslenia?
|
|
|
![]()
Post
#13
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Na razie mój pomysł dotyczy korzystania w aplikacji z jednej bazy.
Przykładowy plik konfiguracyjny: Kod [Db] Type = mysql Host = 127.0.0.1 Port = 3306 User = user Password = pass Base = test2 Interfejs:
Klasa do obsługi Mysql:
Wszystkie metody będę w ten sam sposób wywoływane (te same parametry) aby zachować możliwość zmiany klasy beż konieczności przerabiania kodu aplikacji. Sposób tworzenia obiektu zależeć będzie od sposobu implementacji klasy. Mam klasę Config (wzorowałem się na sposobie hwao - uprościłem ją i zmieniłem), która parsuje plik ini i tworzy klasę z właściwościmi statycznymi, która jest dołączana do aplikacji. Wywołanie będzie się odbywać mniej więcej w taki sposób.
Jeśli napiszę więcej klas do obsługi innych baz przerobi się to na switch'a W ten sposób to widze. Problemem może być tak jak pisałem wyżej, jeśli zechcemy korzystać w jednej aplikacji z kilku różnych baz. Można też zamiast if lub switch dołączać klasę w ten sposób:
ale to już drobnostka.. |
|
|
![]()
Post
#14
|
|
Grupa: Przyjaciele php.pl Postów: 1 224 Pomógł: 40 Dołączył: 6.07.2004 Skąd: Wuppertal Ostrzeżenie: (0%) ![]() ![]() |
czyli bedzie mniejwięcej tak:
? moze to glupie pytanie ale co jeśli będziesz chciał zrobić zapytanie w pętli? Stworzysz drugą instancję Cube_Mysql? (wiem ze tego się nie uzywa ale teoretyzuję). |
|
|
![]()
Post
#15
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
? moze to glupie pytanie ale co jeśli będziesz chciał zrobić zapytanie w pętli? Stworzysz drugą instancję Cube_Mysql? (wiem ze tego się nie uzywa ale teoretyzuję). Stosowanie zapytań w pętli jest tak samo ble jak global. Ale skoro teoretyzujemy to.. hmm.. nie widzę problemu (być może nie widzę problemu) ale ja chcę to rozwiązać tak.
|
|
|
![]()
Post
#16
|
|
Grupa: Przyjaciele php.pl Postów: 1 224 Pomógł: 40 Dołączył: 6.07.2004 Skąd: Wuppertal Ostrzeżenie: (0%) ![]() ![]() |
|
|
|
![]()
Post
#17
|
|
Grupa: Zarejestrowani Postów: 1 190 Pomógł: 27 Dołączył: 23.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
|
|
|
![]() ![]() |
![]() |
Aktualny czas: 22.08.2025 - 22:37 |