Singleton do obsługi bazy danych w PHP - czy używać i jak?

0

Witam.
Zastanawiam się nad zastosowaniem wzorca Singleton do obsługi bazy danych, Zacząłem nawet implementować, ale po drodze pojawiły się wątpliwości co do sensu zastosowania go. Mianowicie moje wątpliwości wzięły się z tego, ze mimo zastosowania tego rozwiązania które z założenia miał nie pozwalać na otwieranie kolejnych połączeń z bazą, w kolejnych plikach php w których potrzebowałem połączenia z db musiałem tworzyć nowe obiekty a nie mogłem skorzystać z utworzonego wcześniej (albo przynajmniej tak mi się wydaje, dlatego piszę bo może ktoś mnie wyprowadzi z błędu).

W każdym razie mój kod wygląda następująco:

singleton.php

<?php
class Singleton {
    
    static $instancja = false;
    private $nazwa;
    private $pass;
    private $login;
    private $serwer;
    
    private function __construct() {
        ;
    }
    private function __clone() {
        ;
    }
    static function instancja(){
        if(empty(self::$instancja)) self::$instancja=new Singleton ();
        return self::$instancja;
    }
    
    public function dbConnect($s,$p,$u,$n){
        $this->setPass($p);
        $this->getPass();
        $this->setServer($s);
        $this->setUser($u);
        $this->setName($n);
        @mysql_connect($this->serwer,$this->user,$this->pass) or die('Brak połączenia z serwerem MySQL.<br />Błąd: '.mysql_error());
        echo "Udało się połączyć z serwerem!<br />";
        @mysql_select_db($this->nazwa) or die('Brak połączenia z bazą danych.<br />Błąd: '.mysql_error());
        echo "Udało się połączyć z bazą dancych!"; 
    }
    
    public function setPass($p){
        $this->pass=$p;
    }
    
    public function setServer($s){
        $this->serwer=$s;
    }
    
    public function getServer(){
        return $pass; 
    }
    public function setUser($u){
        $this->user=$u;    
    }
    
    public function setName($n){
        $this->nazwa=$n;    
    }
    
    public function getName(){
        return $nazwa;    
    }
}
?>

plik1.php

        include "singleton.php";
                        $instance=Singleton::instancja();
                        $instance->dbConnect("localhost","haslo","user","nazwa");
                        $tmp=mysql_query("SELECT NAZWISKO FROM KIEROWCY WHERE ID_KIEROWCY='1'");
                        $temp=mysql_fetch_row($tmp);
                        echo $temp[0]; 

plik2.php

 
                        include "singleton.php";
                        $instance2=Singleton::instancja();
                        $instance2->dbConnect("localhost","haslo","user","nazwa");

I teraz czy to ma sens (działa w każdym razie) ale czy spełnia założenia singletona? Bo ja tego nie widzę, jak dla mnie to i tak po przeładowaniu z plik1.php do plik2.php najpierw zamykane jest jedno połączenie a naste pnie otwierane w kolejnym pliku drugie a to mogę osiągnąć nie korzystając z singletona. Proszę o sugestie czy mam zły tok myślenia czy w kodzie coś jest nie tak.

0

Ale jeżeli plik1.php i plik2.php nie są wykonywane jeden po drugim (przy jednym żądaniu) - a zakładam, że nie są, skoro robisz include, a nie include_once - to choćbym nie wiem jak złożył tą klasę - to przecież i tak połączenie zostanie zamknięte (chyba, że użyjesz mysql_pconnect). Jeżeli z kolei wykonywane są jeden po drugim - to przecież nie zamykasz połączenie, a zobacz sobie jak działa metoda instancja - jeżeli już jest instancja, czyli jesteś połączony - nie tworzy nowego połączenia.

A zupełnie inna rzecz - ta klasa jest zupełnie nieprzydatna. Tyle linijek, żeby wykonać dwa polecenia, a zapytania i tak klepać używając mysql_query? Nawet indetyfikatora połączenia MySQL nigdzie nie zapisujesz. Zupełny brak zastosowania tego ;)

0
dzek69 napisał(a)

Ale jeżeli plik1.php i plik2.php nie są wykonywane jeden po drugim (przy jednym żądaniu) - a zakładam, że nie są, skoro robisz include, a nie include_once - to choćbym nie wiem jak złożył tą klasę - to przecież i tak połączenie zostanie zamknięte (chyba, że użyjesz mysql_pconnect). Jeżeli z kolei wykonywane są jeden po drugim - to przecież nie zamykasz połączenie, a zobacz sobie jak działa metoda instancja - jeżeli już jest instancja, czyli jesteś połączony - nie tworzy nowego połączenia.

A zupełnie inna rzecz - ta klasa jest zupełnie nieprzydatna. Tyle linijek, żeby wykonać dwa polecenia, a zapytania i tak klepać używając mysql_query? Nawet indetyfikatora połączenia MySQL nigdzie nie zapisujesz. Zupełny brak zastosowania tego ;)

Pliki są przykładowe nie chciałem wrzucać całego kodu. Powiedzmy że pliki są wykonywane jeden po drugim, ale nie wiem co rozumiesz przez to ze są wykonywane w jednym żądaniu? Co do obsługi zapytań przez singletona, po prostu jeszcze ich nie dodałem bo zacząłem się zastanawiać czy singleton jest mi potrzebny i przydatny. Co do zapisywania identyfikatora połączenia mysql, to ocb, w jaki sposób to zrobić? Aha i jeszcze jedno pytane techniczne: czy podczas przeładowania pliku zamykane jest połączenie z bazą? Jeżeli tak to jak zastosować mysql_connect?

0

Że są wykonywane w jednym żądaniu - czyli np user wchodzi na index.php, z tego pliku includujesz plik1.php, a potem plik2.php i dopiero gdzieś potem kończy się działanie skryptu. To jest jedno żądanie. Dwa żądania to jak plik1.php i plik2.php są np. osobnymi podstronami. Raczej opcja druga, bo robiąc include definiowałbyś klasę Singleton (co za nazwa) dwa razy, co bodajże wypluje błąd w php.

"podczas przeładowania pliku" - nie ma czegoś takiego. Przeładować można podstronę. Więc teraz napisz mi, czy o to Ci chodzi. Tak, po zakończeniu skryptu wszystkie połączenia z bazą danych są zakańczane. ALE! Tak powinno być. mysql_pconnect otwiera stałe połączenie - przy następnym żądaniu jeżeli połącznie jest dostępne php użyje go, zamiast otwierać nowe. Z tym, że mysql_pconnect w zasadzie nie powinieneś używać jeżeli nie łączysz się do bazy zdalnej (gdzie podłączenie się zajmuje trochę czasu). Te informacje można znaleźć w manualu.

Co do identyfikatora połączenia - jeżeli miałbyś dwa połączenia - z dwoma bazami - to musisz je rozróżniać, tak? mysql_connect zwraca identyfikator połączenia do bazy, który podajesz w m.in. mysql_query - jeżeli go nie podasz, to wykonane zostanie zapytanie do ostatnio utworzonego połączenia, jeżeli jednak nie będziesz zapisywał sobie gdzieś w atrybucie klasy tego identyfikatora - to nie będziesz mógł wykonać zapytania z użyciem pierwszego połączenia. To także można znaleźć w manualu.

I w sumie powyższy akapit (możliwość łączenia do wielu baz danych) sugeruje, że singleton jest złym pomysłem na klasę bazy danych. Tj. wszystko można rozwiązać, np. przekazując dodatkowe parametry itd, ale jakoś nie wyglądałoby mi to "naturalnie".

0

Co do sensu stosowania singletona w PHP i w ogóle: http://4programmers.net/Forum/PHP/188713-singleton_-_moduly_do_cms

0

nie uzywaj singletona, uzyj dependency injection

0

dzek69 i wskaźnik dzięki za podpowiedzi, trochę rozjaśniło mi to. Niestety Cepa sorek uparł się ze ma być zastosowany singleton i nijak nie idzie go przekonać, najwyżej wrzucę to mu tyle ze będzie niefunkcjonalne, niech ma.

1 użytkowników online, w tym zalogowanych: 0, gości: 1