Você está na página 1de 14

Abstrao de Base de Dados utilizando DAO

Bom, ontem me peguei pensando em algo para escrever aqui no blog, e me ocorreu que nunca encontrei muitos textos por ai falando sobre a utilizao de DAO com PHP, e que por ser algo que venho usando h algum tempo agora, e que me ajuda bastante, decidi escrever um texto que procura explicar como um DAO funciona, e como pode ser utilizado. Segue abaixo ento, o texto. Em caso de dvidas, sinta-se a vontade de deixar um comentrio ai, ou me escrever : ) Abstrao de Base de Dados utilizando DAO Autor: Henrique <henrique@heap.com.br> Data: 05/02/2007 Indice 0. Introduo 1. Como funciona? 2. A classe VO (Value Object) 3. A classe DAO (Data Access Object) 4. Utilizao 5. Consideraes Finais 6. Bibliografia 0. Introduo Por muitas vezes, o desenvolvedor de sistemas, se depara com um grande problema quando necessita atualizar a base de dados da sua aplicao, ou modificar uma query em algum lugar. Quando o sistema fica grande demais, as queries se perdem em meio ao cdigo, e tudo se torna uma grande baguna. H casos, em que o desenvolvedor precisa migrar o software de um SGDB para outro, e ai da-lhe correria para encontrar todas as queries e corrigi-las para funcionar com o novo SGDB. Para resolver esse tipo de problema, foi criado um padro, para centralizar as queries, e permitir que alterando apenas a classe referente a tabela no banco, possamos ter a aplicao rodando sem problemas. 1. Como funciona? A idia por trs do DAO, bastante simples: transformar as tabelas de nosso banco de dados em classes VO, e as aes que podemos realizar em classes DAO. As explicaes e exemplos dados nesse texto, iro se basear todos na seguinte estrutura de base de dados, utilizando MySQL como SGDB de escolha.
create table cliente ( id_cliente int not null primary key auto_increment, nome varchar(30), sobrenome varchar(30), endereco varchar(50),

telefone varchar(20) ) engine=INNODB;create table conta ( id_conta int not null primary key auto_increment, id_cliente int, numero_conta varchar(12), numero_agencia varchar(8), tipo_conta varchar(20), foreign key(id_cliente) references cliente(id_cliente) ) engine=INNODB;

A partir daqui, iremos criar as classes VO e DAO de cada uma dessas tabelas, e ento demonstrar uma maneira simples de utilizao, que pode ser aprimorada, em combinao com outros patterns, ou at mesmo com a utilizao da imaginao. Ficar ento, ao critrio do leitor. 2. A classe VO (Value Object) A classe VO, a classe que ir fazer a abstrao das tabelas de nosso banco de dados. Ela uma classe que contm apenas os mtodos get e set para cada uma das propriedades, que nada mais so que os campos das tabelas. A classe da tabela cliente ento, ficar da seguinte maneira:
<?php class ClienteVO { /** * * @var integer */ private /** * * @var string */ private /** * * @var string $nome = NULL; $id_cliente = NULL;

*/ private /** * * @var string */ private /** * * @var string */ private public } /** * Return the value of "$this->id_cliente" * * @return integer */ public { return $this->id_cliente; } /** * Define the value of "$this->id_cliente" * * @return void */ public { $this->id_cliente = $id_cliente; function setId_cliente ( $id_cliente ) function getId_cliente ( ) $telefone = NULL; function ClienteVO ( ) { $endereco = NULL; $sobrenome = NULL;

} /** * Return the value of "$this->nome" * * @return string */ public { return $this->nome; } /** * Define the value of "$this->nome" * * @return void */ public { $this->nome = $nome; } /** * Return the value of "$this->sobrenome" * * @return string */ public { return $this->sobrenome; } /** * Define the value of "$this->sobrenome" function getSobrenome ( ) function setNome ( $nome ) function getNome ( )

* * @return void */ public { $this->sobrenome = $sobrenome; } /** * Return the value of "$this->endereco" * * @return string */ public { return $this->endereco; } /** * Define the value of "$this->endereco" * * @return void */ public { $this->endereco = $endereco; } /** * Return the value of "$this->telefone" * * @return string */ public function getTelefone ( ) function setEndereco ( $endereco ) function getEndereco ( ) function setSobrenome ( $sobrenome )

{ return $this->telefone; } /** * Define the value of "$this->telefone" * * @return void */ public { $this->telefone = $telefone; } } ?> function setTelefone ( $telefone )

Deve ser criada uma classe do mesmo tipo para a tabela conta. No colocarei o cdigo aqui, para evitar de prolongar o texto demais com cdigo. Aconselho ao leitor, criar a classe da tabela conta manualmente, para pegar a prtica do funcionamento da classe, e memorizar o seu layout. Agora que as classes esto criadas, vamos partir para a criao das classes DAO, pois sem elas, as classes VO nos so inteis. 3. A classe DAO (Data Access Object) As classes DAO so as responsveis por realizar o acesso aos dados, em nossa base de dados. Normalmente, as classes DAO podem ser do tipo Singleton, pois no a necessidade de se manter mais de uma instancia da mesma, j que os dados sero todos armazenados nas classes VO. Caso no esteja familiarizado com o conceito de Singleton, recomendo que d uma pesquisada no assunto, pois vale bastante a pena. Nesse texto, criarei as classes DAO sem utilizar da pattern Singleton, para facilitar a visualizao do funcionamento, para quem no conhece esse pattern. O DAO que irei demonstrar, ter apenas alguns mtodos bsicos de busca, e tambm um mtodo para inserir registros, um para atualizar e um para apagar. Voc no precisa limitar sua classe DAO a apenas esses mtodos, podendo criar mtodos de busca que lhe sejam mais teis. Vejamos ento:
<?php class ClienteDAO { /**

* Mtodo que recebe um objeto do tipo ClienteVO * e insere seus valores na base de dados * * @param $objVo ClienteVO */ public function insert( ClienteVO $objVo ) { $values = array( addslashes( $objVo->getNome( ) ), addslashes( $objVo->getSobrenome( ) ), addslashes( $objVo->getEndereco( ) ), addslashes( $objVo->getTelefone( ) ) ); $sql = sprintf('insert into cliente (nome, sobrenome, endereco, telefone) values( "%s","%s","%s","%s" )', addslashes( $objVo->getNome( ) ), addslashes( $objVo->getSobrenome( ) ), addslashes( $objVo->getEndereco( ) ), addslashes( $objVo->getTelefone( ) ) ); mysql_query( $sql ); $objVo->setId_cliente( mysql_insert_id( ) );

return $objVo; }

/** * Mtodo que retorna todos os registros da tabela * em um array de objetos VO *

* @return array Array com objetos VO */ public function getAll( ) {

$objVo = new ClienteVO( ); $return = array( );

$sql = 'select * from cliente'; $resultado = mysql_query( $sql ); while( $rs = mysql_fetch_array( $resultado ) ) {

$objVo->setId_cliente( stripslashes( $rs['id_cliente'] ) ); $objVo->setNome( stripslashes( $rs['nome'] ) ); $objVo->setSobrenome( stripslashes( $rs['sobrenome'] ) ); $objVo->setEndereco( stripslashes( $rs['endereco'] ) ); $objVo->setTelefone( stripslashes( $rs['telefone'] ) );

$return[] = clone $objVo; }

return $return;

} /** * Retorna o objVo, referente ao valor de id especificado * para o campo de chave primria da tabela * * @param $id int Valor do campo de chave primria

* @return ClienteVO Objeto VO com os dados referentes ao registro */ public function getById( $id ) { $objVo = new ClienteVO( ); $sql = sprintf( 'select * from cliente where id_cliente = "%s"', $id ); $resultado = mysql_query( $sql ); while ( $rs = mysql_fetch_array( $resultado ) ) { $objVo->setId_cliente( stripslashes( $rs['id_cliente'] ) ); $objVo->setNome( stripslashes( $rs['nome'] ) ); $objVo->setSobrenome( stripslashes( $rs['sobrenome'] ) ); $objVo->setEndereco( stripslashes( $rs['endereco'] ) ); $objVo->setTelefone( stripslashes( $rs['telefone'] ) );

$return = clone $objVo; }

return $return; }

public function update( ClienteVO $objVo ) {

if ( !$objVo->getId_cliente( ) ) throw new Exception( 'Valor da chave primria invlido' );

$sql = sprintf('update cliente set nome="%s", sobrenome="%s", endereco="%s", telefone="%s" where id_cliente = "%s" ', addslashes( $objVo->getNome( ) ), addslashes( $objVo->getSobrenome( ) ), addslashes( $objVo->getEndereco( ) ), addslashes( $objVo->getTelefone( ) ) ); mysql_query( $sql );

public function delete( ClienteVO $objVo ) { if ( $objVo->getId_cliente( ) == null ) throw new Exception('Valor da chave primria invlido.');

$sql = sprintf('delete from cliente where id_cliente = "%s"', $objVo->getId_cliente( ) ); mysql_query( $sql );

public function save( ClienteVO &$objVo ) {

if ( $objVo->getId_cliente( ) !== null ) { $this->update( $objVo );

} else { $this->insert( $objVo ); } } } ?>

Nessa classe DAO, voce pode criar por exemplo um mtodo de busca que receba um objeto VO como parametro, ou um mtodo que receba um nome de campo e um valor, ou que receba um valor para limit na query, ento use a imaginao quando for criar os mtodos que lhe forem ser teis. Podemos ver que, as queries esto todas nesse arquivo, ento quando existir a necessidade de utilizar um novo SGDB por exemplo, basta escrever as classes DAO para esse novo SGDB, e o sistema dever funcionar normalmente. A seguir, veremos como utilizar as classes DAO/VO, em um exemplo bastante simples. 4. Utilizao Tendo os DAOs e VOs criados, podemos utiliza-los de maneiras diversas. No exemplo que montei acima, utilizei as funes de mysql diretamente no DAO, sem estabelecer nenhuma conexo, pois assumi que a conexao ser inicializada no comeo da execuo do script. Caso o leitor deseje, pode criar uma forma de inicializar a conexo, ao instanciar a classe DAO por exemplo. Irei criar agora ento, um simples formulrio para cadastro de clientes, que faz um submit para a prpria pgina, e utiliza mtodo POST.
<?phpif( isset($_POST['enviar']) ) { // Conectar na base de dados mysql_connect('localhost','root',''); mysql_select_db('daoTutorial'); // Incluir classe VO include_once('clientevo.class.php'); // Incluir classe DAO include_once('clientedao.class.php'); // Instanciamos o objeto VO, e o preenchemos $cliente = new ClienteVO( ); $cliente->setNome( $_POST['nome'] ); $cliente->setSobrenome( $_POST['sobrenome'] ); $cliente->setTelefone( $_POST['telefone'] );

$cliente->setEndereco( $_POST['endereco'] ); $clienteDAO = new ClienteDAO( ); $cliente = $clienteDAO->insert( $cliente ); printf('Registro inserido com sucesso. O id do cliente %s<br><br>', $cliente->getId_cliente( )); } ?> <html> <head> <title>Exemplo uso de DAO</title> </head> <body> <form method='POST'> Nome: <input type='text' name='nome'><br> Sobrenome: <input type='text' name='sobrenome'><br> Endereo <input type='text' name='endereco'><br> Telefone <input type='text' name='telefone'><br>

<input type='submit' value='Enviar' name='enviar'> </form> </body> </html>

Acessando essa pagina, um formulrio simples ser apresentado. Quando preenchido e submetido, o php ir checar se o boto enviar foi realmente clicado, e caso sim, o objeto VO ser preenchido com as informaes que foram passadas no formulrio, e far com que a classe DAO insira esses dados na base de dados. O mtodo insert da classe DAO retorna o objeto preenchido com os dados, mais ovalor que recebeu como chave primria. Para testar esse exemplo, no esquea de colocar a classe VO e a classe DAO no mesmo diretorio que se encontra o script, e arrumar as informaes de conexo com a base de dados. Se deseja listar todos os registros da base de dados, pode criar um script de listagem, com cdigo semelhante ao que segue:
<?php // Conectar na base de dados

mysql_connect('localhost','root','');

mysql_select_db('daoTutorial'); // Incluir classe VO include_once('clientevo.class.php'); // Incluir classe DAO include_once('clientedao.class.php'); $clienteDAO = new ClienteDAO( ); // pega todos os clientes $clientes = $clienteDAO->getAll( ); if( sizeof($clientes) > 0 ) { // verifica se h algum cliente cadastrado foreach( $clientes as $objVo ) { printf('Nome: %s <br>',$objVo->getNome( )); printf('Endereo: %s <br>', $objVo->getEndereco( )); echo '<hr><br>'; } } ?>

Os mtodos de update e delete, exigem que o campo de chave primria esteja preenchido para realizarem a sua ao, ento fique atento a isso. 5. Consideraes finais Os exemplos apresentados, no do muita importancia a segurana, embora apresentem algumas boas prticas de programao, como procurar comentar o cdigo. Percebam que uma medida de segurana tomada, ao usar o comando addslashes nas queries SQL, para evitar injection, mas isso apenas pode no ser o bastante. Uma filtragem dos dados mais bem feita com certeza se faz necessria. Veja tambm que no mtodo de update, no feita nenhuma verificao, para saber se o registro realmente existe na base de dados, antes de tentar atualizar, o que pode causar problemas. A pattern DAO pode ser combinada com outras patterns, para desenvolvimento de sistemas de todos os portes, e bastante interessante pois concentra toda a relao com o banco de dados em um s lugar, e permite que o filtro das informaes que so enviadas, possa ser feito nesse mesmo lugar, facilitando a tomada de medidas de segurana no desenvolvimento. 6. Bibliografia No consigo me lembrar exatamente que textos li para me aprofundar nesse assunto, nem quais sites visitei, j que h algum tempo que utilizo isso. Devo agradecer ao Carlos (que provavelmente nem vai ler esse texto), pois ele me apresentou o conceito de DAO. Talvez possa encontrar algo no google, que possa

ter informaes interessantes. Encontrei um texto no site da IBM,que parece interessante:

Você também pode gostar