Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

AprendendoC

Sugestões - php pdo

Mensagens Recomendadas

AprendendoC

buenas galera, tudo bom!

bom tenho aqui umas classes que estou criando para aprender.

classe de conexao com o banco de dados

<?php
class Conexao extends PDO {
	private $dataBase = 'mysql';
	private $host = 'localhost';
	private $dbName = 'nome_do_banco';
	private $user = 'nome_usuario';
	private $pass = 'senha_usuario';
	static $conexao = NULL;

	public function __construct(){
		try{
			self::$conexao = parent::__construct($this->dataBase.':host='.$this->host.';dbname='.$this->dbName, $this->user, $this->pass);
			self::$conexao = parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		}catch(PDOException $e){
			echo 'Erro ao se conectar a base de dados'.$e->getMessage();
		}
	}// __construct

	public function __destruct(){
		self::$conexao = NULL;
	}// __destruct

	public function insert($dados, $tabela){
		//INSERT INTO tabela (campos) VALUES (valores)
		$sql = "INSERT INTO ".$tabela." (";
		foreach($dados as $key => $value):
			$campos[] = $key;
			is_numeric($value) ? $valores[] = $value : $valores[] = "'".$value."'";
		endforeach;
		$sql .= implode(", ", $campos).") VALUES (".implode(", ", $valores).")";
		$query = $this->prepare($sql);
		$query->execute();
		echo $sql;
	}// insert

	public function update($dados, $tabela){}
	public function select($dados, $tabela){}
	public function delete($dados, $tabela){}

}// Conexao
?>

classe Usuarios

require_once("Conexao.class.php");
// estendo a classe usuarios da classe conexao para fazer as transaçoes com o banco.
class Usuarios extends Conexao {
	private $nome;
	private $email;
	private $senha;

	public function setNome($nome){
		$this->nome = $nome;
	}// setNome

	public function setEmail($email){
		$this->email = $email;
	}// setEmail

	public function setSenha($senha){
		$this->senha = $senha;
	}// setSenha

	public function getNome(){ return $this->nome; }
	public function getEmail(){ return $this->email; }
	public function getSenha(){ return$this->senha; }

// criei essa funcao para inserir os dados no banco, chamando a funcao insert(classe da conexao)
//não sei se é correto fazer isto, mas esta funcionando.
  	 public function inserir($dados, $tabela){
		//pega as variaveis da classe e as coloca em um array $dados
		$dados = get_object_vars($dados);
		//chama a função insert da classe pai
		parent::insert($dados, $tabela);
	}
} // Usuarios
?>

teste.php onde faço os teste pra ver se esta funcionando

<?php
require_once("Usuarios.class.php");

$user = new Usuarios();

// insiro dados nas variaves da classe Usuarios
$user->setNome("Testando as classses");
$user->setEmail("teste@teste.com");
$user->setSenha("12345");

// chamo a funcao inserir (classe usuarios) e passo pra ela o objeto criado da propria classe e
// a tabela que desejo inserir os dados.
// testei e está funcionando tudo certo, fez a inserção no banco de dados sem dar erro algum.
$user->inserir($user, "tabela_usuarios");
?>

e ai pessoal nao sei se o que eu fiz está correto, pois estou fazendo para aprender...

entao gostaria da opiniao dos mais experientes se está correto o que estou fazendo, se

posso fazer assim, e sugestoes de melhorias.

desde já agradeço a todos!

Editado por AprendendoC

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
HappyHippyHippo

ora bem ... tens aqui pano para mangas ...

1º -

Se queres ter esse tipo de relação entre classes, então a classe Conexao deverá ser abstracta sendo impossível instânciar-la por si só:

$conexao = new Conexcao(); // <-- isto é possivel nesse código.

deverias tornar a função __construct protegida para que isso não aconteça e possa ser chamada pela classe derivada

<?php
class A {
   protected function __construct() {
       echo "__construct class A<br />";
   }
}

class B extends A {
   // é obrigatório ter esta função porque senão o construtor da classe A será chamado
   // no entanto, como é protegido, vai dar bronca ao tentar instânciar a classe B
   public function __construct() {
       parent::__construct(); // não esquecer de chamar o construtor da classe A (isto não é C++ ou Java, tens de fazer à mão)

       echo "__construct class B<br />";
   }
}

$obj1 = new B(); // __construct class A
                // __construct class B

$boj2 = new A(); // ERRO : impossível instâncias a classe
?>

2º -

as funções CRUD da classe Conexao, não fazem sentido serem públicas. o que achas que faz sentido :

$obj = new Usuarios();

// esta ?
$obj->insert(array("id", 1), "my table");

// ou esta ?
$obj->insert(array("id", 1));

a primeira até poderia bem dar bronca se te enganasses a colocar o nome da tabela ...

o que deverias fazer seria alterar o nivel de acesso das funções CRUD da classe Conexao protegidas e teres funções frontend na classe Usuarios

class Conexao {
 protected function insert($dados, $tabela) {
   // ...
 }
}

class Usuarios {
 static protected $tabela = "tbl_usuarios"; // eu explico a palavra "static" mais à frente

 public function insert($dados) {
   parent::insert($dados, self::$tabela);
 }
}

3º -

apesar do ponto anterior estar a funcionar, a própria maneira como a função se apresenta não faz muito sentido ...

pensa bem, estás a manusear um objecto, não vais estar a dizer a um objecto para inserir outro pois não ?

$user1 = new Usuarios();
$user2 = new Usuarios();

$user1->inserir($user2); // <-- pedir a "user1" para inserir "user2" ???

pois bem, a função inserir (e afins) não deveriam ter o parâmtro dados, porque é suporto serem acções sobre os dados da classe/objecto instânciado

class Usuarios {
 static protected $tabela = "tbl_usuarios"; // eu explico a palavra "static" mais à frente

 public function insert() {
   parent::insert(get_object_vars($this), self::$tabela);
 }

 public function update() {
   parent::insert(get_object_vars($this), self::$tabela);
 }
}

$user = new Usuarios();
// ...
$user->insert(); // inserir a si próprio na base de dados
// ...
$user->update(); // actualizar os seus próprios dados na base de dados

4º -

vamos supor que é para usar o modelo apresentado.

o que acontece se tiveres duas instâncias da classe Usuarios ?

$user1 = new Usuarios();
$user2 = new Usuarios();

- quantas ligações à base de dados existem ?

- e se tiveres outro tipo de dados que deriva também de Conexao ?

- e quantas instâncias desses outros tipos de dados irás ter ?

- quantas ligações irâo ser no final ?

estás a ver o problema ?

pois é ... é por isso que não se faz assim. tens duas soluções:

- fazes a convencial separação dos classes guardando uma referência da classe Conexao na class Usuarios

class Conexao {
 public function __construct() { // terá de ser publica porque terás de instâncias a classe
 }
}

class Usuarios {
 protected $conexao;

 public function __construct($conexao) {
   $this->conexao = $conexao;
 }
}

$conexao = new Conexao();
$user1 = new Usuarios($conexao);
$user2 = new Usuarios($conexao);

como podes ver, agora só existirá uma ligação à base de dados

tens ainda uma outra solução mais engraçada, que é a combinação de um design pattern chamadoSingleton com a derivação convencional do OOP. algo semelhante ao teu código, mas com algumas alterações

<?php
class Conexao {
   static protected $conexao = null; // nota no uso da palavra reservada "static", é uma variável de classe e não de instância da classe
                                     // isto quer dizer que é transversal a todas as instâncias da classe

   protected function __construct() {
       if (self::$conexao == null) { // verificar se a ligação à base de dados já foi efectuada
                                     // nota : usar sempre o "self::" para referênciar a variável !!!
                                     //        caso contrário, uma nova variável local com o mesmo nome será criada
           echo "connetion initialization<br />";
           // ...
       }
   }

   protected function conexao() {
       return self::$conexao; // não esquecer do "self::"
   }
}

class Usuarios extends Conexao {
   public function __construct() {
       parent::__construct(); // <-- não esquecer !!!
   }
}

$user1 = new Usuarios(); // vai criar a ligação à base de dados
$user2 = new Usuarios(); // este já não vai criar a ligação à base de dados
?>

  • Voto 1

IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
taviroquai

<?php
require_once("Usuarios.class.php");
$user = new Usuarios();
$user->setNome("Testando as classses");
$user->setEmail("teste@teste.com");
$user->setSenha("12345");
$user->inserir($user, "tabela_usuarios");
?>

@AprendendoC

O que queres fazer chama-se de ORM, ou seja, queres ter um objecto que represente um utilizador (usuario) e queres que esse objeto possa ser inserido/guardado/apagado de uma base de dados relacional. Eu também já fiz uma ORM apenas para Mysql e também já existem algumas ORMs para PHP e digo-te que são todas de alguma complexidade...

Se fosse eu a fazer, não tornava a classe Usuario extensão da Classe conexão. Na classe Usuario adicionava propriedades de metadados para indicar à classe Conexao algumas informações necessárias para saber guardar os dados.

Podias ter uma API assim:

<?php
$usuario = new Usuario();
$usuario->setNome('bla');
$usuario->setMetaTable('tbl_usuarios'); // Algumas ORMs nem precisam disto porque fazem a sua própria gestão de nomes de tabelas...

// Até aqui tens um simples objecto independente de bases de dados

// Agora se quiseres o CRUD...
$orm = new Conexao('pdo string...');
$orm->save($usuario); // isto serve tanto para inserir (se não existir) como para alterar
$orm->delete($usuario); // isto serve para apagar
$orm->find('tbl_usuarios', ' email like ?', array('%@teste.com%')); // faz um select e devolve objectos Usuario com os metadados

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
yoda

Talvez assim fosse mais simples :

<?php
	$user = new User;

	$user->name = 'Testando as classses';
	$user->email = 'teste@teste.com';
	$user->password = '12345';

	$user->update();

       class User extends ORM {} // User extende ORM que tem os métodos insert, select, delete, ..
       class ORM extends PDO {} // ORM extende PDO para interacção directa com a base de dados

?>

Editado por yoda

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
AprendendoC

@HappyHippyHippo

@Rui Carlos

@taviroquai

@yoda

Muito obrigado pelas opiniões e dicas, vou estudar e implementar o restante me baseando nas explicações de vocês!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.