+3

Implementando o padrão Singleton com PHP5

criado por Diego Botelho Martins em 31/12/2006 7:57am
O padrão singleton define uma instância única para um determinado objeto. Seu construtor não fica visível ao objeto de forma que não se pode instanciá-lo através de $con = new conexao; mas sim dessa forma: $obj = conexao::singleton();

O método singleton() irá verificar se já existe uma instância dessa classe previamente utilizada, caso exista ele a retorna, caso contrário ele cria uma nova instância.

Temos uma classe de conexão com o banco de dados, o construtor dessa classe realiza a conexão e seleciona o bd.
Imagine que iremos utilizar este objeto para diversas consultas diferentes. Cada consulta abrirá uma conexão com o mysql, o que irá sobrecarregá-lo caso muitos usuários acessem a página simultamenamente.

Você pode estar se perguntando... porque não utilizar mysql_pconnect() ?? Bom, pelo simples fato de que não nos interessa ter uma conexão constantemente aberta por motivos até mesmo de segurança.

Vejamos como ficaria o código:

<?php
class Exemplo
{
    // Guarda uma instância da classe
    static private $instance;
   
    // Um construtor privado
    private function __construct() 
    {
        $link = mysql_connect('localhost', 'root', ''); 
        if (!$link) {
            die('Não foi possível conectar: ' . mysql_error()."<br><br>");
        }
        echo '<br><br>Conexão bem sucedida.<br><br>';

        $db_selected = mysql_select_db('teste', $link);
        if (!$db_selected) {
            die ('Não foi possível selecionar : ' . mysql_error());
        }
    }

    // O método singleton 
    static public function singleton() 
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }
   
    // Método exemplo
    public function consultar($sql)
    {
        $result = mysql_query($sql);
        if (!$result) {
            die('<br><br>Consulta Inválida: ' . mysql_error());
        }
    }
}

// Isso sempre vai recuperar uma instância da classe
echo "objeto1: ";
$test = Exemplo::singleton();
$test->consultar('select * from clientes');

echo "<br>objeto2: ";
$test2 = Exemplo::singleton();
$test2->consultar('select * from pedidos');

echo $test." ".$test2;
?>

Comentários:

Mostrando 1 - 10 de 19 comentários
A função serialize não permite armazenar variáveis do tipo resource.

http://br.php.net/manual/pt_BR/function.serialize.php
11/12/2009 6:40pm (~7 anos atrás)

Obrigado Flávio, a idéia é exatamente essa.
08/03/2007 5:59am (~9 anos atrás)

Galera todo padrão que se pensar em utilizar é util em relação ao contexto do problema , no caso em que nos encontramos aqui, eu acho que seria um alívio p servidor evitando que o script atual crie a cada necessidade uma nova instancia de conexão !! muito legal o script !! vlw diego botelho !
07/03/2007 6:32am (~9 anos atrás)

Já tinha utilizado o padrão Singleton, e quando se sabe usar, é realmente muito bom!!!

Falou
21/02/2007 7:39pm (~9 anos atrás)

Jose Berardo disse:
Permitam-me meter o dedo na polêmica, mas também andei me aventurando a escrever algo a respeito.
A quem interessar, http://joseberardo.blogspot.com.

Abraço a todos
08/02/2007 6:53pm (~9 anos atrás)

Com a polêmica que foi gerada, escrevi um artigo no meu blog explicando o real funcionamento do Singleton no PHP, segue o link a quem interessar:

http://feliperibeiro.blogspot.com/2007/01/desmistificando-o-singleton-no-php_17.html
04/02/2007 6:42pm (~9 anos atrás)

Bom trabalho!! muito bom.
29/01/2007 6:28am (~10 anos atrás)

Marcos Regis disse:
Realmente. Fiz o teste e o objeto apenas se mantem para uso no mesmo script.

Nesse caso o melhor é mesmo usar o serialize()/unserialize() (automático quando se salva o objeto em sessão).

Quanto a conexão. O melhor é ainda usar o pconnect para economizar conexões pois o PHP não fecha a conexão ao final do script e assim ele reaproveitará qq uma que esteja aberta.
Então não vejo vantagem alguma em usar Singleton pois nem para melhor compreensão do código facilita.
Talvez a unica coisa útil seria quando se tem um classe que chama métodos de outra classe e assim é melhor evitar contruir um novo objeto a cada chamada de uma função deste.
Sei que o PHP consegue compartilhar areas da memória (shmop) que podem ficar acessíveis a qq execução de script e nesse caso sim daria pra criar um objeto que ficasse instanciado para todos os visitantes como o Java faz mas não estudei isso ainda.

19/01/2007 8:05am (~10 anos atrás)

Se você quiser que o objeto seja persistente entre uma página e outra você pode tentar utilizar serialize() e unserialize()

http://www.php.net/manual/pt_BR/function.serialize.php

Ela gera uma representação de um objeto em uma string que pode ser salva na seção e recuperada posteriormente.

Abraços
18/01/2007 2:33am (~10 anos atrás)

Galera, o objeto é unico dentro da execução do script atual, em outra sessão outro objeto será criado e obviamente outra conexão também.
O singleton é util quando você quer evitar várias conexões abertas dentro do mesmo script.

Só isso já alivia bastante o servidor.

Um abraço
18/01/2007 2:25am (~10 anos atrás)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)