Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Beto Lima

[Resolvido] pdo + singleton

Recommended Posts

João,

 

Objetivo seria deixar a conexão e a chamada do getInstance() da Registry em uma classe / arquivo separado, quando fosse usar apenas chamaria o metodo getMyInstance da classe conexão e passaria a query.

 

Obrigado pelo apoio.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Na minha opnião para usar singleton no PHP devemos declarar o retorno do getInstance como retorno by reference.

 

public static function &getInstance() {

Se não criaremos cópias do objeto, e não a mesma instancia... estou enganado?

 

$a = Singleton::getInstance();

$a->setExemplo('sou o A');

 

//em outro momento...

$b = Singleton::getInstance();

$b->setExemplo('sou o B');

 

echo $a->getExemplo(); //sou o A

echo $b->getExemplo(); //sou o B

 

Quando na verdade os 2 deveriam retornar o mesmo valor...

 

ops... fiz o teste aqui e isso que eu disse está errado...

Na verdade não precisa do retorno by reference... achei estranho. Pensei que no PHP o uso do = copiava a instância...

Compartilhar este post


Link para o post
Compartilhar em outros sites

ops... fiz o teste aqui e isso que eu disse está errado...

Na verdade não precisa do retorno by reference... achei estranho. Pensei que no PHP o uso do = copiava a instância...

 

Rogério, o fragmento abaixo ilustra a situação:

 

<?php
class Teste {
private static $counter = 0;

private $inum;

public function __construct(){
	$this->inum = ++self::$counter;

	printf( "Construindo objeto %d\n" , $this->inum );
}

public function __destruct(){
	--self::$counter;
	printf( "Destruindo objeto %d\n" , $this->inum );
}

public function __clone(){
	printf( "Clonando objeto %d\n" , $this->inum );

	$this->inum = ++self::$counter;

}
}

$i1 = new Teste();
$i2 = new Teste();
$i3 = $i1;

printf( "i1 == i2 ? %s\n" , $i1 == $i2 ? 'sim' : 'não' );
printf( "i2 == i3 ? %s\n" , $i2 == $i3 ? 'sim' : 'não' );
printf( "i3 == i1 ? %s\n" , $i3 == $i1 ? 'sim' : 'não' );

$i4 = clone $i1;

printf( "i4 == i1 ? %s\n" , $i4 == $i1 ? 'sim' : 'não' );
printf( "i4 == i2 ? %s\n" , $i4 == $i2 ? 'sim' : 'não' );
printf( "i4 == i3 ? %s\n" , $i4 == $i3 ? 'sim' : 'não' );

 

A saída será:

Construindo objeto 1

Construindo objeto 2

i1 == i2 ? não

i2 == i3 ? não

i3 == i1 ? sim

Clonando objeto 1

i4 == i1 ? não

i4 == i2 ? não

i4 == i3 ? não

Destruindo objeto 3

Destruindo objeto 2

Destruindo objeto 1

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

tirando o tópico do coma...

 

        public static function getInstance() {
                if ( !self::$instance )
                        self::$instance = new Registry();

                return self::$instance;
        }

essa getInstance ela server unicamente pra não duplicar o objeto Registry, é isso?

 

$registry = Registry::getInstance();

$registry-> set( 'Banco de dados' , 'class banco1' );

 

$registry = Registry::getInstance();

$registry-> set( 'Banco de dados alternativo' , 'class banco2' );

 

 

a getInstance poderia ser chamada dentro da função set?

outra duvida...

 

Registry::getInstance()

Registry::umaCoisa()

Registry::umaCoisa()

acima foi criada apenas 1 instancia da classe, e a função umaCoisa foi executada duas vezes

 

Registry::umaCoisa()

Registry::umaCoisa()

ja nesse, instancia da classe foi criada 2 vezes

 

 

é assim que funciona?

não consegui visualizar muito bem esse funcionamento...

ao fazer Registry::xx, ja não estaria criando uma instancia naturalmente, independentemente de checar a instancia criada???

Compartilhar este post


Link para o post
Compartilhar em outros sites

não.

 

só se instancia objetos.

se você usar métodos estáticos, você não tem objeto, portanto não tem instancia.

 

essa getInstance ela server unicamente pra não duplicar o objeto Registry, é isso?

Sim, o getInstance() no Registry, serve para fazer um Singleton, e não instanciar o Registry mais de uma vez.

 

a getInstance poderia ser chamada dentro da função set?

não, nem tem como. Já que para usar a set, você precisa de uma instancia o objeto.

 

Registry::umaCoisa()
Registry::umaCoisa()
ja nesse, instancia da classe foi criada 2 vezes
só se dentro do metodo umaCoisa(), você tiver um new Registry(), se não, você não está criando objeto nenhum ai.

 

 

ao fazer Registry::xx, ja não estaria criando uma instancia naturalmente, independentemente de checar a instancia criada???

nops, e é aqui que reside toda a tua dúvida.

Se você usar Class::metodo(), você não está usando um objeto(portanto não tem instancia), mas a sim a classe.

Compartilhar este post


Link para o post
Compartilhar em outros sites

ao fazer Registry::xx, ja não estaria criando uma instancia naturalmente, independentemente de checar a instancia criada???

nops, e é aqui que reside toda a tua dúvida.

Se você usar Class::metodo(), você não está usando um objeto(portanto não tem instancia), mas a sim a classe.

 

:)

 

então Class::metodo() so 'acessa' a função e pronto acabou?

o que é diferente de

$Class = new Class

$Class-> metodo()

 

se for assim, eu estava tendo uma visão que era apenas uma forma alternativa de instanciar o obj

[]s

Compartilhar este post


Link para o post
Compartilhar em outros sites

João batista, muito boa a sua resposta.

 

Eu estive estudando o singleton e muitos exemplos dizem de utilizar com BD. Ai, ao concluir o meu estudo, fiz a pergunta que você respondeu: E se minha aplicação tiver que acessar bases diferentes? O singleton vai barrar isso... tentei de várias maneiras uma forma de contornar esta situação com singleton, porém, a idéia do singleton é clara e realmente LIMITA esse uso.

 

Vou dar uma conferida no pattern Registry mencionado.

 

 

Vlw.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Gostei muito desse tópico. Já lí bastante sobre o assunto mas por aí, parece que a galera que detém conhecimento não curte muito o "compartilhar" no sentido real da palavra. Enfim, minha experiência:

 

Estava procurando uma forma de implementar uma ideia do Beraldo discutida no tópico http://forum.imasters.com.br/topic/439254-cadastrar-sub-categorias/ e senti certa dificuldade de trabalhar com o então script em OO.

 

Lendo o presente tópico, ví uma solução aplicando a usabilidade do Registry Pattern sugerido pelo João e achei bem interessante pensar em singleton quando realmente precisa se usar singleton.

 

Testei e meu resultado foi assim:

 

 

Numa classe Categoria.php tenho o codigo já implementando o registry...

 

$db = new MySQLConnect();
        
        $registry = SingleResgistry::getInstance();
        $registry->set( 'PDO' , $db->getConnection() );

        // lista categorias
        $registry = SingleResgistry::getInstance();
        $pdo = $registry->get( 'PDO' );
        $stm = $pdo->query( 'select * from categorias where id_pai=0' );
        
        $c = new CategoriaHandle();
        $indent = "--";
        
        
        echo "<select name=\"pai\">
              <option value=\"0\">Categoria Primaria</option>";

	$stm->execute();
	  while($l = $stm->fetch(PDO::FETCH_ASSOC)){

		echo "<option value='$l[id]'>$l[nome]</option>";
		$c->exibe_filhos($l["id"],$indent);
          }

        echo "</select>";

Criei uma classe chamada CategoriaHandle onde os métodos exibe_filhos() (saída para form) e lista_filhos() (saída para list) fossem buscar no banco as listas solicitadas pela classe Categoria. Aí residia o problema, pois precisaria fazer novas consultas ao banco. Passando valores retornados da classe Categoria por parâmetros não dava certo, consumo excessivo de memória e outros problemas. Com registry bastava buscar a instância já existente, sem a necessidade de abrir uma nova conexão em ambos os métodos. Assim:

 

public function exibe_filhos($id_categoria, $indent=""){
        
        $registry = SingleResgistry::getInstance();

        // lista categorias
        $registry = SingleResgistry::getInstance();
        $pdo = $registry->get( 'PDO' );
        
        $tb = $pdo->prepare("select * from categorias where id_pai=:pai");
	$tb->bindParam(":pai",$id_categoria, PDO::PARAM_INT);
	$tb->execute();
	
	while($l = $tb->fetch(PDO::FETCH_ASSOC)){
		echo "<option value='$l[id]'>$indent $l[nome]</option>";
                // lista subcategorias
		self::exibe_filhos($l["id"], $indent . $indent);
	}
        
    }

    public function lista_filhos($id_categoria, $indent=''){
    (... mais códigos ...)

Além de deixar uma certa organização, economiza muitas linhas de códigos...

 

Obrigado pela aula que vocês deram.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado João Batista Neto, muito bom trabalhar com registry e sua classe é muito boa, obrigado mesmo por compartilhar seu conhecimento com a gente!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Estou com uma dúvida.

 

Quando crio um $pdo da forma abaixo

 

$pdo = new PDO( 'mysql:host=127.0.0.1;dbname=nome_do_banco' , 'usuario' , 'senha' );


para depois adicionar em um registry

 

 

$registry = Registry::getInstance();$registry->set( 'PDO' , $pdo );


e aplico isso na inicialização de minhas páginas.

Eu não estou criando múltiplas instâncias de $pdo a cada página diferente?

$pdo = new PDO( 'mysql:host=127.0.0.1;dbname=nome_do_banco' , 'usuario' , 'senha' );

 

pelo menos uma vez preciso usar da forma acima e só depois usarei assim:

$registry = Registry::getInstance();$pdo = $registry->get( 'PDO' ); 

 

como eu devo criar o $pdo para armazenar em um registry pela primeira vez? Não ficou claro pra mim nas explicações acima.

 

[]

Noleto Júnior

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você cria uma instância a cada fluxo de requisição. PHP é um tanto quanto "único" nesse quesito.

 

Veja esta thread:

http://forum.imasters.com.br/topic/474083-afinal-pra-server-o-singleton/

 

Ps.: Evita ressuscitação de tópicos antigos, crie um novo e, caso necessário, linke-o.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Visitante
Este tópico está impedido de receber novos posts.

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.