Ir para conteúdo

POWERED BY:

Arquivado

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

Cassiano Oliv

classes [Estudos]

Recommended Posts


Bom dia,


Tenho uma classe simples:


class FuncoesBD




public function setTabela($tabela, $alias = NULL) {
if(!is_null($alias) || empty($alias)) {
$this->alias = $alias;
$this->tabela = $tabela . ' ' . $this->alias;
}
else {
$this->tabela = $tabela;
}
}

public function setCampos($campos) {
if(is_array($campos)) {
foreach($campos as $campo) {
$this->campos .= $campo . ', ';
}
$this->campos = substr($this->campos, 0, -2);
}
else {
$this->campos = $campos;
}
}

public function setValores($valores) {
if(is_array($valores)) {
// extrais os campos e valores
foreach($valores as $campo => $valor ){
$this->campos .= $campo . ', ';
$this->valores .= is_string($valor) ? $this->conexao->quote($valor) . ', ' : $valor . ', ';
}
$this->campos = substr($this->campos, 0, -2);
$this->valores = substr($this->valores, 0, -2);
}
else {
throw new Exception('Parâmetro inválido.');
}
}

public function consulta($condicao = NULL, $ordem = NULL, $limiteInicio = NULL, $limiteFim = NULL) {
$this->condicao = !empty($condicao) && !is_null($condicao) ? ' WHERE ' . $this->antiSQL($condicao) : '';
$this->ordem = !empty($ordem) && !is_null($ordem) ? ' ORDER BY ' . $this->antiSQL($ordem) : ''; //$this->conexao->quote($ordem)
$this->limite = $limiteInicio != '' && $limiteFim != '' && !is_null($limiteInicio) && !is_null($limiteFim) ? ' LIMIT ' . $this->antiSQL($limiteInicio) . ', ' . $this->antiSQL($limiteFim) : '';

return $this->conexao->query("SELECT " . $this->campos . " FROM " . $this->tabela . $this->join . $this->condicao . $this->ordem . $this->limite . "");
//return "SELECT " . $this->campos . " FROM " . $this->tabela . $this->join . $this->condicao . $this->ordem . $this->limite . "";
}




Quero realizar uma consulta e retornar os dados da tabela:


class Login




class Login extends FuncoesBD {
public $consulta;
private $respostaConsulta;
private $campos;

public function verificaLogin($login, $senha) {
$this->consulta = $this->consulta("login = '" . $login . "' && senha = '" . $senha . "'");
$this->respostaConsulta = $this->consulta->rowCount();

return $this->respostaConsulta;
}

public function getDados() {
// metodo para retornar um array com os dados da tabela. Ex: array("nome" => "cassiano", "sobrenome" => "oliveira")
}
}




Página para recuperar os dados




require_once("classes/login.php");

$obj = new Login;
$obj->setTabela("admin");
$obj->setCampos(array("login", "senha"));
$consulta = $obj->verificaLogin($login, $senha);

if($consulta > 0) {
// aqui quero usar o método getDados para retornar os dados da tabela
}


Podem me dar uma luz?

Desde já agradeço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você esta tratando o objeto login como se fosse um objeto do banco (no caso uma tabela).

 

Minha pergunta é, isso parece sensato pra você?

 

Sim a resposta for sim você deve procurar por DAO (Data Acess Object).

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Vinicius,

 

Não entendi sobre ser sensato.

 

A classe login é para tratar o login de uma página e retornar os dados do usuário.

Fazendo testes, consegui realizar a consulta:

$obj = new Login;
$obj->setTabela("admin");
$obj->setCampos(array("login", "senha"));
$consulta = $obj->verificaLogin($login, $senha);

$dados = $consulta->fetch();
		$id = $dados->id;
		$grupoID = $dados->grupoID;
		$nome = $dados->nome;
		$ultimoLogin = $dados->ultimoLogin;
		$login = $dados->login;
// Assim consegui resgatar os dados.

Depois me surgiu outra dúvida...

Essa exibição de dados fiz diretamente na página onde o objeto foi criado.

Minha dúvida, posso fazer desta forma ou é melhor criar um método "getDadosLogin()" na class login?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Na verdade a forma inteira esta errada é o que estou tentando dizer.

 

Conceitualmente seu código esta falho.

 

Você esta tratando o Objeto "Login" como se fosse um Objeto de Banco o que não é verdade.

 

Os design patterns são padrões para que você não precise quebrar a cabeça com problemas que muitos já procurarão soluções.

 

No seu caso o pattern correto seria o DAO como citei, leia um pouco mais sobre ele que você vai entender melhor o que quero dizer.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vinícius, li sobre DAO e acho que entendi a metodologia.

Basicamente, para cada tabela do meu banco terei duas classes, uma com os "sets/gets" e outra para manipular os dados/métodos na base de dados, certo?

 

Veja meu exemplo:

*OBS: Irei reduzir os códigos para melhor interpretação.

 

conexao.php

class ConexaoBD {
	protected $conexao;
	
        private $servidor;
	private $BD;
	private $usuario;
	private $seha;
	
	# realiza conexão à base de dados
	public function __construct() {
        try {
            $this->servidor = 'localhost';
			$this->BD = 'teste';
			$this->usuario = 'root';
			$this->senha = '';
			
			//Cria a conexão ao MySQL
            if($this->conexao == NULL) {
                $this->conexao = new PDO('mysql:host=' . $this->servidor . ';port=3306;dbname=' . $this->BD, $this->usuario, $this->senha, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
				$this->conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
				$this->conexao->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
                return $this->conexao;
            }
        }
        catch(PDOException $e) {
            echo 'Falha ao realizar conexão à base de dados.<br /><br />
			Erro técnico: ' . $e->getMessage() . '<br />
			Arquivo: ' . basename($e->getFile()) . '<br />
			Linha: ' . $e->getLine() . '<br />';
        }
    }
	
    }
	
	# finaliza conexão com a base de dados
	public function fechaCnx() {
		$this->conexao = NULL;
	}
}

clientes.php

class Clientes {
	private $nome;
	private $email;
	
	public function setNome($nome) {
		$this->nome = $nome;
	}
	
	public function setEmail($email) {
		$this->email = $email;
	}
	
	public function getNome() {
		return $this->nome;
	}
	
	public function getEmail() {
		return $this->email;
	}
}

clientesDAO.php (a dificuldade aqui)

class ClientesDAO {
	private $tabela;
	private $conexao;
	
	private function __construct() {
		$this->tabela = 'clientes';
	}
	
	public function setCampos($campos) {
		...
	}
	
	public function setValores($valores) {
		...
	}
	
	public function cadastrar($obj para efetuar conexao com o banco e utilizar métodos PDO) {
		...
	}
}

Atualmente, na limitação de meu conhecimento, eu estenderia a classe conexão para efetuar conexão com a base de dados e utilizar os métodos do PDO.

 

Como faço para utilizar um parâmetro para manipular a conexão e os métodos do PDO nas classes DAO sem estender a classe conexão?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Por que você manipularia isso dentro do DAO?

 

Você esta trabalhando com objetos instanciáveis para a conexão (eu não costumo trabalhar desse jeito) mas enfim.

public function __construct($server='localhost',$db='teste',$user='root',$pass='') {
try {
$this->servidor = $server;
            $this->BD = $db;
            $this->usuario = $user;
            $this->senha = $pass;
            
            //Cria a conexão ao MySQL
if($this->conexao == NULL) {
$this->conexao = new PDO('mysql:host=' . $this->servidor . ';port=3306;dbname=' . $this->BD, $this->usuario, $this->senha, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
                $this->conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                $this->conexao->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
return $this->conexao;
}
}

E então para cada objeto você poderia instanciar um DB ou um usuário diferente e criar varias conexões o que acho que não vá acontecer.

 

Exemplo:

$conexao1 = new conexaoDB(); //conexão padrão, banco teste, usuário root sem senha
$conexao2 = new conexaoDB('root','client2'); //conexão padrão, banco client2, usuário root sem senha

E então esse objeto vai ser passado como parâmetro no método de cadastrar do seu DAO.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Na verdade, eu quero passar acessar o objeto "conexao" da classe de conexão para poder acessar o banco na classe ClienteDAO. Ex:

<?php
public function cadastrar() {
     $this->conexao->query(...); // quero poder usar os métodos PDO na classe Noticias, Fotos, etc...
}
?>

Como está atualmente, preciso instanciar a conexao, e passar o por parâmetro em todas as páginas que eu for acessar o banco:

<?php
$conexao = new Conexao;

$x = new ClienteDAO;
$x->cadastrar($conexao);
?>

em cadastrar() da classe ClienteDAO
<?php
public function cadastrar($objConexao) {
     $objConexao->query($minhaSQL);
}
?.

Por isso no início do tópico, eu extendia a classe conexão para poder acessar/alterar o banco já que as classes que manipulam as tabelas recebem objeto $conexao da classe conexao.php.

 

Conseguiu entender minha ideia?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Um exemplo melhor:

class.conexao.php

class ConexaoBD {
	protected $conexao;
	private $servidor;
	private $BD;
	private $usuario;
	private $seha;
	
	# realiza conexão à base de dados
	public function __construct() {
        try {
            $this->servidor = 'localhost';
			$this->BD = 'cms';
			$this->usuario = 'root';
			$this->senha = '';
			
			//Cria a conexão ao MySQL
            if($this->conexao == NULL) {
                $this->conexao = new PDO('mysql:host=' . $this->servidor . ';port=3306;dbname=' . $this->BD, $this->usuario, $this->senha, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
				$this->conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
				$this->conexao->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
                return $this->conexao;
            }
        }
        catch(PDOException $e) {
            echo 'Falha ao realizar conexão à base de dados.<br /><br />
			Erro técnico: ' . $e->getMessage() . '<br />
			Arquivo: ' . basename($e->getFile()) . '<br />
			Linha: ' . $e->getLine() . '<br />';
        }
    }
}

class.clienteDAO.php

class ClientesDAO {	
	...
	outros métodos aqui
	...
	
	public function cadastrar() {
		// sem estender a classe conexão não consigo usar os métodos PDO, "query" por exemplo.
                // o objeto conexao está na classe conexao.php e não consigo manipulá-lo nesta classe...
                return $this->conexao->query($minhaSQL);
	}
}

Para fazer uma consulta no banco, por exemplo, tenho de estender:

class ClientesDAO extends ConexaoBD {	
	...
	outros métodos aqui
	...
	
	public function cadastrar() {
		// agora eu consigo executar o método "query" do PDO. No entanto, como você mesmo disse no início do tópico, não é o ideal estender a classe.
                return $this->conexao->query($minhaSQL);
	}
}

Como faço para utilizar o objeto conexao de class.conexao.php sem estender?

Se eu não estender eu sempre vou ter de instanciar a conexao para passar o parâmetro, mas acho desnecessário fazer isso para notícias, fotos, etc... Estendendo, a conexao já é instanciada em cada classe DAO.

 

Espero que consiga entender.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Eu refatoraria sua classe ConexaoBD assim:




<?php
class ConexaoBD {
private $host;
private $name;
private $user;
private $pswd;


public function __construct( $host, $name, $user, $pswd ) {
$this->host = $host;
$this->name = $name;
$this->user = $user;
$this->pswd = $pswd;
}


public function conectar()
{
try {


$conexao = new PDO('mysql:host=' . $this->host . ';port=3306;dbname=' . $this->name,
$this->user, $this->pswd, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')
);
$conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conexao->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

return $conexao;
} catch(PDOException $e) {
echo 'Falha ao realizar conexão à base de dados.<br /><br />
Erro técnico: ' . $e->getMessage() . '<br />
Arquivo: ' . basename($e->getFile()) . '<br />
Linha: ' . $e->getLine() . '<br />';
}
}
}



Coloquei os dados de conexão no método construtor, pois, sem esses dados, a conexão não funciona, então podem ir no construtor. Al~em disso, você deixa para o metodo conectar, somente a responsabilidade de fazer a conexão propriamente dita.


Para usar no seu DAO, sem extender, use injeção de dependência (leia sobre isto!) no seu método construtor (leia sobre isto!):




<?php
class ClientesDAO {
private $bd;


public function __construct( PDO $conexaoBD )
{
$this->bd = $conexaoBD;
}


public function cadastrar() {


return $this->bd->query($minhaSQL);
}
}



Veja que o BD deve ser uma instância de PDO... Assim, usando injeção de dependência, você diz que o seu DAO USA a conexao. Usando herança, você diz que seu DAO É uma conexão... e não é né?!


Usando...




<?php
$BD = new ConexaoBD( 'localhost', 'cms', 'root', '123456' );
$conexao = $BD->conectar();


$clientesDAO = new ClientesDAO( $conexao );

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa noite Riberry,

 

Interessante a Injeção de Dependência, ainda não havia lido sobre.

Fiz sua implementação com uma pequena alteração na classe conexao.php, no entanto, a variável $conexao tem de ser pública para funcionar:

 

Veja:

class ConexaoBD {
	public $conexao; // <<== aqui sendo protected ou private gera erro
	private $servidor;
	private $BD;
	private $usuario;
	private $senha;
	
	# realiza conexão à base de dados
	public function __construct() {
        try {
            $this->servidor = 'localhost';
			$this->BD = 'testes';
			$this->usuario = 'root';
			$this->senha = '';
			
			//Cria a conexão ao MySQL
            if($this->conexao == NULL) {
                $this->conexao = new PDO('mysql:host=' . $this->servidor . ';port=3306;dbname=' . $this->BD, $this->usuario, $this->senha, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
				$this->conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
				$this->conexao->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
                return $this->conexao;
            }
        }
        catch(PDOException $e) {
            echo 'Falha ao realizar conexão à base de dados.<br /><br />
			Erro técnico: ' . $e->getMessage() . '<br />
			Arquivo: ' . basename($e->getFile()) . '<br />
			Linha: ' . $e->getLine() . '<br />';
        }
    }
}

ClientesDAO.php

<?php
require_once("conexao.php");
require_once("clientes.php");

class ClientesDAO {
	public $tabela;
	private $bd;
	
	public function __construct() {
		$this->bd = new ConexaoBD;
	}
	
	public function selecionar($sql) {
		return $this->bd->conexao->query($sql);
	}
}
$conecta = new ConexaoBD();

$clientesBD = new ClientesDAO($conecta);
$dadosClientes = $clientesBD->selecionar('SELECT * FROM clientes');
while($dado = $dadosClientes->fetch()) {
	echo $dado->nome . '<br>';
}
?>

Está funcionando, mas achei estranho "$conexao" ter de ser "public".

Fiz algo errado?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá amigo,

 

Tem razão, a propriedade $conexao não deve ser public, e sim protected ou private. Pesquise um poquito más sobre encapsulamento e visibilidade. Leitura recomendada:

 

http://forum.imasters.com.br/topic/392735-php-orientado-a-objetos/

 

No seu código, nem existe a necessidade de criarmos uma propriedade conexão. Eu deixaria assim:

$conexao = new PDO( 'mysql:host=' . $this->servidor . '; port=3306;dbname=' . $this->BD, 
$this->usuario, 
$this->senha,
array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')
);
$conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conexao->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);


return $conexao;
Se quiser continuar com a propriedade $conexao em sua classe, você deve setá-la como private (ou protected, caso deseje trabalhar com herança, mas acho que ela não cabe aqui.) e fazer algo do tipo:
class Database
{
private $pdo;
private $host;
private $name;
private $user;
private $pswd;
private $port;
 
public function __construct( $host, $name, $user, $pswd, $port = 3306 )
{
$this->host = $host;
$this->name = $name;
$this->user = $user;
$this->pswd = $pswd;
$this->port = $port;
 
$this->setConnection();
}
 
public function setConnection()
{
try {
            $this->pdo = new PDO( $this->host, $this->name, $this->user, $this->pswd );
$this->pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$this->pdo->setAttribute( PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ );
 
        } catch(PDOException $e) {
            echo 'Falha ao realizar conexão à base de dados.<br /><br />
Erro técnico: ' . $e->getMessage() . '<br />
Arquivo: ' . basename($e->getFile()) . '<br />
Linha: ' . $e->getLine() . '<br />';
        }
}
 
public function getConnection()
{
return $this->pdo;
}
}
Usando...
<?php
$database = new Database( 'localhost', 'cms', 'root', '123' );
$connection = $database->getConnection();
 
$userDAO = new UserDAO( $connection );
Perceba que não deixei tudo no método construtor... Separei em dois métodos, uma para conectar, e outro para obter a conexão, usando assim o tal do encapsulamento... com o método getConnection(), você pode recuperar a conexão de fora da classe... Pois não podemos acessar uma propriedade privada de fora da classe. Espero que tenha ajudado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

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