Jump to content
AprendendoC

Sugestões - php pdo

Recommended Posts

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!

Edited by AprendendoC

Share this post


Link to post
Share on other 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
?>

  • Vote 1

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

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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

?>

Edited by yoda

Share this post


Link to post
Share on other 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!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.