You are on page 1of 21

CRUD Genéricos em PHP.

1ª Parte: Create
criado por Marcio Alexandre em 02/05/2010 3:13pm Primeramente explicando o que é CRUD: Create [criar], Retrieve [recuperar], Update [atualizar] e Delete [excluir]. Quero deixar registrado que o foco aqui não é a performance do sistema, ok?! Afinal de contas, as 'tags' que caracterizam esse artigo é bem específico ;) Vamos iniciar, com este, um conjunto de 5 artigos explicando como fazer o famoso CRUD em php orientado à objetos, de forma que não precisemos criar este conjunto de ações a quantidade de vezes que houver funções de acesso a base. Ou seja, nossos objetos estarão mais enxutos e não importando a regra de negócio, poderemos obter as informações necessárias, puxadas no banco de dados, nas camadas acima, utilizando SEMPRE a mesma função, modificando apenas os parâmetros enviados. Basicamente, nas estruturas DAO, já temos os dados do objeto em questão. Como já sabemos para cada objeto temos a estrutura que receberá cada dado referente à sua tabela no banco. Além disso temos também todas as ações deste objeto no sistema (inserts, updates, deletes, selects). Sabendo que este objeto tem um estrutura semelhando à tabela do banco, podemos incrementar um pouco mais essas informações afim de que ela se comunique com nossas classes genéricas, e execute o que está sendo solicitado. Por questão de organização e segurança, deixei as classes CRUD dentro do objeto de conexão com o banco. E nos objetos (DAO) nós importamos as classe e alimentamos os parâmetros. Vamos lá, trazendo o código referente a um funcionário (funcionarioDAO.php), já no padrão de acesso às classes genéricas:
class funcionario{ private $nome_tabela = 'tb_funcionario'; private $camposInsert = 'fun_nome,fun_data'; var $id_funcionario; var $fun_nome; var $fun_data; public function setDados($id_funcionario,$fun_nome,$fun_data){ if (isset($id_funcionario)){ $this->id_funcionario = $id_funcionario ; }else{$this->id_funcionario = null; } $this->fun_nome = $fun_nome ; $this->fun_data = $fun_data ; } public function getId(){ return $this->id_funcionario;} public function getNome() { return $this->fun_nome; } public function getDataBr() { /*modelo brasil (00/00/0000 00:00)*/ $temp = explode(' ',$this->fun_data); $temp_data = explode('',$temp[0]); $data = $temp_data[2].'/'.$temp_data[1].'/'.$temp_data[0]; $hora = $temp[1]; return $data.' '.$hora ; } public function getDataEn() { return $this->fun_data; } public function getNomeTabela() { return $this->nome_tabela; public function getNomeCampos() { return $this->camposInsert; } public function getValorCampos() { return "'".$this>fun_nome."','".$this->fun_data."' "; } }

public function Salvar($objeto,$db){ $db->insertObjectToDB($objeto); } public function Atualizar($objeto,$db){ $db>updateObjectToDB($objeto); } public function Pegar($fields,$values,$db){ return $db>selectDataDb($this->getNomeTabela(),$fields,$values);} public function PegarTodos($fields,$values,$db){ return $db>selectDatasDb($this->getNomeTabela(),$fields,$values); } public function Deletar($fields,$values,$db){ $db->DeleteDataDb($this>getNomeTabela(), $fields,$values); } }

Observe que adicionamos mais duas variáveis privadas, no objeto, uma que traz o nome da tabela no banco, e a outra trazendo os fields (campos), em sequência como utilizamos nos inserts em sql. Também inserimos duas funções para trazer os valores dessas duas variáveis. Adicionamos também uma função ( getVAlorCampos() ) que retorna uma string com alguns dados na mesma seqüência da variável privada referente aos campos da tabela ($camposInsert), para inserir os dados. A outras variáveis e funções são comuns aos DAOs. Na função salvar nós enviamos o objeto em questão, já alimentado, e a variável de referencia ao banco, que traz as classes genéricas. Observe que é necessário um padrão de nomenclaturas entre o objeto (nome dele mesmo) e o nome da tabela e seus campos. Para tornar o fluxo de informação viável numa classe genérica temos que usar estes padrões: • Nome dos objetos: funcionarioDAO,clienteDAO,produtoDAO. • Nome da classe:funcionario,cliente,produto (respectivamente) • Nome das tabelas: tb_funcionario,tb_cliente,tb_produto (respectivamente). • Nome das páginas: funcionario.php,cliente.php,produtos.php (respectivamente). Adotando este padrão será possível acessar qualquer tabela baseada no objeto enviado, pois o nome será lido a partir do objeto inserido na classe, e o fluxo automático de páginas no sistema. Vejamos como a classe de inserção é construída, esta classe estará dentro do objeto „banco.php‟ (que traz consigo também a abertura de fechamento do banco Mysql):
class Banco{ private $local; private $user; private $senha; private $msg0; private $msg1; private $nome_db; private $db; public function __construct(){ $this->local = $this->user = $this->senha = $this->msg0 = $this->msg1 = de dados!'; $this->nome_db = }

'localhost'; 'root'; ''; 'Conexão falou, erro: '.mysql_error(); 'Não foi possível selecionar o banco 'db_sistemaqualquer';

$closed = NULL.'</font><br><br>'."(".")". } public function fechar(){ //analisar se o mysql_close precisa ser colocado numa variável $closed = mysql_close($this->db).$objeto->getValorCampos().$objeto->getNomeTabela(). header('location: '.$temp_id[1]. charset=iso-88591"> </head> <body> <?php if (!$_POST){ $msg = @$_REQUEST['msg'].public function abrir(){ $this->db = mysql_connect($this->local. Agora o mais simples.rio</title> <meta http-equiv="Content-Type" content="text/html. } $link = explode('/'. } } //class Simples assim.") VALUES ( ". mysql_select_db($this->nome_db.$objeto->getNomeTabela()). } public function insertObjectToDB($objeto){ $db = new Banco(). unset($objeto). o formulário de inserção: <html> <head> <title>Cadastro de Funcion&aacute. E com os próprios dados que vem do objeto.$objeto>getNomeCampos(). echo '<br>'.php?msg=Inserido').$this->db) or die($this->msg1). ?> <form action="<?php echo $link[$qtd-1]. if (isset($msg)){ echo '<font color="red"> '.$msg. A string SQL é montada automaticamente de acordo com os dados que já existem no objeto (neste caso sem wheres. $temp_id = explode('_'. a classe recebe via parâmetro o objeto que quer inserir no banco. ?>" method="post"> <table width="50%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="17%">Nome</td> <td width="49%"><input name="txtNome" type="text" id="txtNome" size="50"></td> </tr> <tr> <td> </td> <td> </td> </tr> <tr> <td> </td> <td><input type="submit" name="Submit" value="Enviar"></td> </tr> .$this->user.$_SERVER ['REQUEST_URI']). obedecendo os padrões de nomenclaturas adotados previamento já direciona para próxima página após a inserção. $db->abrir(). mas nos próximos artigos mostraremos como montar as strings SQL com 1 ou mais wheres). $query = mysql_query($sql) or die ($sql.$this>senha) or die($this->msg0).' '. $qtd = count($link). $sql = "INSERT INTO ".mysql_error()). $db->fechar().'.

} ?> </body> </html> Portanto. 2ª Parte: Retrieve (de um objeto) criado por Marcio Alexandre em 17/06/2010 1:56pm Mais uma vez vamos nós. e não o retorno de uma lista de objetos (isso ficará para o próximo artigo.<tr> <td> </td> <td> </td> </tr> </table> </form> <?php }else{ require('uses/banco.$fun_nome. porque tornar possível a leitura de qualquer table. para cada objeto temos a estrutura que receberá cada dado referente à . espero ter contribuído com uma programação mais prática e sem frameworks pesados e muitas vezes desnecessários. para deixar os artigos independentes. $db = new Banco(). Tornarei a repetir algumas conceitos teóricos.$db). utilizamos o $_SERVER ['REQUEST_URI'] para dar o refresh automático. para não precisar se preocupar com mais este campo do formulário. sem foco no desempenho. e depois salvamos enviando ele mesmo ($func) e a instância do objeto do banco ($db). Atenção: Este artigo se referente às consultas de um determinado dado que alimentará um objeto.. utilizando o mesmo principio de antes. é realmente muito complicado.php'). instanciamos o $func. CRUD Genéricos em PHP. via parâmetro. $func = new funcionario(). Bom. Até a 2ª Parte. require('uses/funcionarioDAO. $func->salvar($func. é isso aí. $fun_nome = $_POST['txtNome'].. onde alimentamos o objeto com os dados fornecidos pelo formulário. Continuemos agora com o Retrieve (ou as famosas „consultas‟). Observando os mesmo conceitos da parte „CREATE‟ destes 5 artigos. Só para clarear. e „varrer‟ suas possíveis fields. deixando mais dinâmico. $fun_data = date('Y-m-d H:i:s').$fun_data). e utilização de SQL dinâmicas para suportar o conceito genérico em OO PHP.php'). Como já sabemos. $func->setDados(null. achei melhor dividir).

' '.$fun_nome. no objeto.php).'/'. ou seja. $this->fun_data = $fun_data . e pode ser 01 ou mais filtros.$fun_data){ if (isset($id_funcionario)){ $this->id_funcionario = $id_funcionario . } public function getNomeTabela() { return $this->nome_tabela.$temp[0]). já no padrão de acesso às classes genéricas: class funcionario{ private $nome_tabela = 'tb_funcionario'."' ". a where pode ser determinada pelo desenvolvedor sem problemas. } public function Deletar($fields.$temp_data[1].$db){ $db->insertObjectToDB($objeto). Explicando os parâmetos. inclusive segurança. private $camposInsert = 'fun_nome.$hora . } public function Atualizar($objeto. em sequência como utilizamos nos inserts em sql.} public function getNome() { return $this->fun_nome.$db){ $db->DeleteDataDb($this>getNomeTabela(). } } Observe que adicionamos mais duas variáveis privadas.fun_data'. este objeto tem um estrutura semelhando à tabela do banco. public function getNomeCampos() { return $this->camposInsert. $temp_data = explode(''. Também inserimos duas funções para trazer os valores dessas duas variáveis. deixei as classes CRUD dentro do objeto de conexão com o banco. } public function getValorCampos() { return "'". } } public function Salvar($objeto. }else{$this->id_funcionario = null.'". $data = $temp_data[2]. uma que traz o nome da tabela no banco.$db){ return $db>selectDatasDb($this->getNomeTabela()."'. $hora = $temp[1].$values).sua tabela no banco.$this->fun_data).$values.$values).$values.$fields. var $fun_nome. Tudo deve ser analisado. Vamos lá. basta informar campo . Aqui está um dos pontos principais do artigo. public function setDados($id_funcionario. var $id_funcionario. } public function getDataBr() { /*modelo brasil (00/00/0000 00:00)*/ $temp = explode(' '. nas camadas superiores a função „Pegar‟.$db){ return $db>selectDataDb($this->getNomeTabela(). $fields. „$fields‟ e „$values‟ são vetores que trazem os campos e seus valores.$temp_data[0]. var $fun_data.$this>fun_nome. portanto. } $this->fun_nome = $fun_nome .'/'. e a outra trazendo os fields (campos). Por questão de organização e segurança.$values). com os quais filtraremos nossos dados no banco (refiro-me à where).$fields. } public function getId(){ return $this->id_funcionario. pois sendo assim. Utilizaremos.$values. } public function Pegar($fields.$this->fun_data. } public function getDataEn() { return $this->fun_data. E nos objetos (DAO) nós importaremos as classe e alimentamos os parâmetros (aqui estará o segredo de manipulação das wheres). trazendo o código referente a um funcionário (funcionarioDAO. return $data.$db){ $db>updateObjectToDB($objeto).} public function PegarTodos($fields.

Agora vamos ver a comunicação da aplicação. nos vetores. ?> <input name="txtNome" type="text" id="txtNome" value="<?php echo $objeto->getNome(). $db = new Banco(). Ok. require('uses/funcionarioDTO. e imprimiremos o nome dele: <html> <head> <title>Atualiza Funcionário</title> <meta http-equiv="Content-Type" content="text/html. $values[1] = $_REQUEST['id']. $msg1. <?php class Banco{ private private private private private $local. Lembro também que caberia aqui qualquer outra Field do banco. estamos querendo trazer um funcionário pelo id dele. E agora alimentaremos o vetor $fields e $value para filtrar os dados do select.$db). e retorna um valor (que iremos abordar mais adiante). conforme vemos no code acima.php acessaria somente a tabela „tb_cliente‟. previamente alimentada com o nome da tabela no banco a que se refere. Nos objetos. a função do banco selectDataDb as recebe. ok?! Nenhuma complicação. Observe a importância de manter o nome da tabela nos demais arquivos. respectivamente. e assim sucessivamente. alimentaremos o objeto funcionárioDAO com todos os dados do banco. Simples. o objeto funcionarioDAO.$values. respectivamente. No caso. a tabela „tb_funcionario„. adicionando a função da própria classe getNomeTabela(). $user. $senha. informamos o campo e o valor. $msg0. Agora vamos entrar na classe do banco e entender. Isso torna cada objeto responsável pela sua tabela no banco. Após enviar os parâmetros para função Pegar. $fun = new funcionario(). como por exemplo clienteDAO. passando os filtros. Neste exemplo.php'). Faremos aqui uma combo (HTML) básica.e valor. Já explicamos a comunicação do objeto consigo mesmo.php'). charset=iso-88591"> </head> <body> <?php require('uses/banco. ?>"> </body> </html> Até aqui nenhuma novidade. e somente só. if (!$_POST){ $fields[1] = 'id_funcionario'.php consulta só. Importamos as classes banco e funcionario. . $objeto = $fun->Pegar($fields. na chamada da função Pegar. sempre teremos a função getNomeTabela() que retorna nossa variável privada $nome_tabela.

$this->senha = ''. $this->user = 'root'.$fields_where. } //garante que o where entre caso tenha algum parâmetro $sql . if ($qtd != count($values_where)){ // verifica o numero de fields e values ?> <script language="javascript"> alert('Função: selectDataDb. valores(values) da consulta $obj = explode('_'. mysql_select_db($this->nome_db." from ".$this>user.$values_where){ $qtd = count($fields_where). $db = new Banco(). Erro: Quantidade de campos diferente da quantidade de valores'). $this->msg1 = 'Não foi possível selecionar o banco de dados!'.$j<=$qtd.$campo. . } public function BuscaValor($campo. private $db. if ($j<$qtd ) { $sql .= $fields_where[$j].$fields_where.$tb_name. $this->msg0 = 'Conexão falou.' = '.$this->senha) or die($this->msg0).$values_where){ // nome da tabela. public function __construct(){ $this->local = 'localhost'. vetores: campos(fields).= ' where '. com os parametros enviados (podendo ser nenhum ou vários) }//else }//public function public function selectDataDb($tb_name. $linha = mysql_fetch_array($res).$tb_name). </script> <?php }else{ // Monta a string SQL===================== $sql = "select ".$values_where[$j]. erro: '. } public function fechar(){ //analisar se o mysql_close precisa ser colocado numa variável $closed = mysql_close($this->db). $closed = NULL.= ' and '. } public function abrir(){ $this->db = mysql_connect($this->local.mysql_error()). if ($qtd != 0 ) { for ($j=1.$tb_name. // retorna o valor do campo especifico. $this->nome_db = 'db_exitosistemas'. return $linha[$campo].$this->db) or die($this->msg1).$j++){ if ($j == 1) { $sql . $new_objeto = new $obj[1].private $nome_db. } } } //======================================= $res = mysql_query($sql) or die ($sql .mysql_error().

. nas demais partes do sistema (nome do objeto. $i). o nome da tabela é „quebrada‟ (ultizando o explode do php).sexo‟. „fisicamente‟... //conta o número de campos for ($i = 0. Não se assuste pelo tamanho e pela quantidade de laços de repetição. A função selectDataDb() recebe os parâmetros enviados pela função Pegar em FuncionarioDAO. nome seria a posição: 1.. $fields_values = $this>BuscaValor(mysql_field_name($fields.$fields_where.$values_where).$tb_name.$tb_name). $i++) { $fields_name = mysql_field_name($fields. Simples assim! Nenhuma novidade. return $new_objeto.$tb_name). Buscar o nome é simples. e por aí vai. é automático. // informa os fields/campos da tabela do banco $columns = mysql_num_fields($fields). endereco: 2. $obj = explode('_'.. da classe. } $db->fechar(). $new_objeto = new $obj[1]. $i++) { $fields_name = mysql_field_name($fields. Nisso tornamos genérica nossa classe. o sistema entender qual objeto será carregado. talvez ajude).. $i < $columns. minha classe tem que entender qual objeto será carregado após o select no banco. $i < $columns. Sendo assim. Qualquer objeto pode ser carregado.endereco. contato: 3. Sabemos que ao acessar o banco. Vamos entender.$tb_name). } ?> Ok! Aqui está a classe. // informa os fields/campos da tabela do banco $columns = mysql_num_fields($fields). para buscar o nome do campo e o valor deste campo. $i). quais e quantas fields que lá existe. Como fazer minha função entender qual objeto o banco irá popular? Agora vai a importância de manter a nomenclatura da tabela do nosso banco. Ao acessar a função selectDataDb().(eu fiz alguns comentários no código. para só então. utilizaremos a função do mysql: mysql_field_name. $fields = mysql_list_fields('db_tabelaqualquer'.). Baseado na quantidade de campos existente. Após isso.$db->abrir(). $fields_values = $this- . e assim sucessivamente. Onde informamos a posição da Field. E sabendo que o objeto carrega em si o nome da própria tabela a que se refere. $i). precisamos „criar‟ um objeto de retorno de dados (obedecendo ao Data Access Object). $fields = mysql_list_fields('db_tabelaqualquer'. //conta o número de campos for ($i = 0. fazemos um laço.contato. $new_objeto->$fields_name = $fields_values. Para entender melhor: se numa tabela eu tenho „nome. nós adentramos e colhemos no banco.

</script> <?php }else{ Caso esteja tudo ok.$values_where). } //garante que o where entre caso tenha algum parâmetro $sql . $this->BuscaValor(mysql_field_name($fields. É só substituir o nomes que costumeiramente é usando nos SQL de consulta.$values_where[$j].= $fields_where[$j]. e já tratamos isso logo no início.$j++){ if ($j == 1) { $sql . $i). Envia-se o nome do campo desejado. } Para buscar o valor. caso haja mais campos e valores a serem concatenados. if ($qtd != 0 ) { for ($j=1. E nisso . trazendo TODOS os que fora passados.= ' and '. $i)..= ' where '.$campo. O IF garante que nossa where receberá algo para ser trabalhado. O laço de repetição varre o vetor.$tb_name. e logo após é concatenado os campos e valores respectivamente. E é aqui que fica a construção de nossa SQL Dinâmica.$fields_where.$values_where). $qtd = count($fields_where). Um coisa linda (me empolguei." from ".>BuscaValor(mysql_field_name($fields. hehehehehe). Nenhum segredo até então. if ($j<$qtd ) { $sql . Quantas cláusulas formarão a where? É necessário saber. o nome da tabela. Entraremos então na função BuscaValor. precisaremos de uma função de auxílio. if ($qtd != count($values_where)){ // verifica o numero de fields e values ?> <script language="javascript"> alert('Função: selectDataDb.$tb_name. Logo na entrada cuidaremos de nosso filtro do select. até a quantidade de campos e valores existe no vetor. O primeiro IF depois do For. } } } A variável $sql recebe o texto concatenado com os novos valores das variáveis. Prosseguimos para a construção real do select. // Monta a string SQL===================== $sql = "select ". Senão o código fica muito complicado. Validamos se a quantidade de fields e seus valores correspondem no IF abaixo.$tb_name. O próximo IF é somente para concatenar a palavra „and‟ à string citada. garante que o a palavra „where‟ seja concatenada na string $sql.' = '.$fields_where. por variáveis que receberão os valores em tempo de execução.$j<=$qtd.. $new_objeto->$fields_name = $fields_values. Erro: Quantidade de campos diferente da quantidade de valores'). e os vetores que construirão nossas wheres.

=) CRUD Genéricos em PHP. ou seja. Acredito. para deixar este artigo independente dos demais. Vamos lá. Observando os mesmo conceitos dos outros dois artigos [Create e Retrieve (de um objeto) ]. Continuemos agora com o Retrieve (ou as famosas „consultas‟) com o retorno de vários objetos (utilizando vetores). Encerro aqui mais este artigo. Qualquer dúvida.. e utilização de SQL dinâmicas para suportar o conceito genérico em OO PHP. trazendo o código referente a um funcionário (funcionarioDAO. Como já sabemos. } $this->fun_nome = $fun_nome . agradeço a atenção. e espero ter contribuído com mais este conhecimento à comunidade OO PHP.$fun_data){ if (isset($id_funcionario)){ $this->id_funcionario = $id_funcionario . =) Próximo artigo: Retrieve (com retorno de um list de objetos populados). E nos objetos (DAO) nós importaremos as classes e alimentaremos os parâmetros (aqui estará o segredo de manipulação das wheres). public function setDados($id_funcionario.fun_data'. este objeto tem uma estrutura semelhando à tabela do banco. já no padrão de acesso às classes genéricas: class funcionario{ private $nome_tabela = 'tb_funcionario'. . sem foco no desempenho. mas nada que não venhamos entender. 3ª Parte: Retrieve (de vários objetos) criado por Marcio Alexandre em 23/06/2010 10:51am Mais uma vez vamos nós. é só entrar em contato. devido ao tamanho. sou Marcio Alexandre. var $id_funcionario. para cada objeto temos a estrutura que receberá cada dado referente à sua tabela no banco. Por questão de organização e segurança. Talvez tenha ficado algo confuso.. private $camposInsert = 'fun_nome. var $fun_data.$fun_nome. deixei as “classes CRUDs” dentro do objeto „banco‟. Tornarei a repetir alguns conceitos teóricos. E mais uma vez. Bom pessoal.consiste a idéia principal do artigo. tendo paciência e atenção. que este será o artigo mais complexo. var $fun_nome. }else{$this->id_funcionario = null. Utilizando o mesmo princípio de antes.php).

$values). Utilizaremos."' "."'. na chamada da função PegarTodos. respectivamente.$this->fun_data). e a outra trazendo os fields (campos). nas camadas superiores a função „PegarTodos‟. inclusive segurança.$db){ $db->DeleteDataDb($this>getNomeTabela().$this->fun_data. em sequência como utilizamos nos inserts em sql. public function getNomeCampos() { return $this->camposInsert. } } Observe que adicionamos mais duas variáveis privadas.'/'. } public function getDataEn() { return $this->fun_data.$hora . $fields. Isso torna cada objeto responsável pela sua tabela no banco. Observe a importância de manter o nome da tabela nos demais arquivos. Ok.$db){ $db->insertObjectToDB($objeto).$temp_data[1]. a tabela „tb_funcionario„.$db){ $db>updateObjectToDB($objeto). uma que traz o nome da tabela no banco. Explicando os parâmetos. $hora = $temp[1]. } public function getValorCampos() { return "'". } public function getId(){ return $this->id_funcionario.php consulta só. e somente só. como por exemplo clienteDAO. $data = $temp_data[2].'".$fields.$this->fun_data = $fun_data . Após enviar os parâmetros para função PegarTodos.$values). a where pode ser determinada pelo desenvolvedor sem problemas. Nos objetos. No caso.$values. e assim sucessivamente. o objeto funcionarioDAO. } public function Atualizar($objeto. portanto.php acessaria somente a tabela „tb_cliente‟.$fields. pois sendo assim. } public function getNomeTabela() { return $this->nome_tabela. basta informar campo e valor. conforme vemos no exemplo acima. previamente alimentada com o nome da tabela no banco a que se refere. e retorna um valor (que iremos abordar mais adiante). no objeto. com os quais filtraremos nossos dados no banco (refiro-me à where). nos vetores.$temp_data[0]. „$fields‟ e „$values‟ são vetores que trazem os campos e seus valores.$db){ return $db>selectDatasDb($this->getNomeTabela(). } public function getDataBr() { /*modelo brasil (00/00/0000 00:00)*/ $temp = explode(' '.$db){ return $db>selectDataDb($this->getNomeTabela(). . Aqui está um dos pontos principais do artigo. E vimos que até agora não existe qualquer diferença com o artigo anterior de pegar apenas um objeto em específico. } public function Pegar($fields.$values.$values.$temp[0]).$values). a função do banco selectDatasDb as recebe.} public function getNome() { return $this->fun_nome. } } public function Salvar($objeto. Também inserimos duas funções para trazer os valores dessas duas variáveis. e pode ser 01 ou mais filtros.$this>fun_nome. $temp_data = explode(''.} public function PegarTodos($fields.' '. Tudo deve ser analisado. adicionando a função da própria classe getNomeTabela(). sempre teremos a função getNomeTabela() que retorna nossa variável privada $nome_tabela.'/'. } public function Deletar($fields. Já explicamos a comunicação do objeto consigo mesmo. return $data.

private $msg1.php').Agora vamos ver a comunicação da aplicação com o objeto. private $nome_db. <?php class Banco{ private $local. $this->nome_db = 'db_exitosistemas'. $this->msg1 = 'Não foi possível selecionar o banco de dados!'.$this->senha) or die($this->msg0). Agora alimentaremos o vetor $fields e $value para filtrar os dados do select dentro do objeto. Lembro também que caberia aqui QUALQUER filtro. mysql_select_db($this->nome_db. e traremos todos eles para nossa aplicação: <html> <body> <?php require('uses/banco. alimentaremos o objeto funcionárioDAO com todos os dados do banco. $objeto = $func->PegarTodos($fields. ?>"><?php echo $obj>getNome(). $this->senha = ''. ok?! Sem nenhum problema. porque não precisa de where específica. $func = new funcionario().php'). foreach($objeto as $m => $obj){ ?> <option value="<?php echo $obj->getId().$db). por isso os fields e values estão vazios. ?></option> <?php } ?> </select> </body> </html> Até aqui nenhuma novidade.mysql_error(). private $user. porém agora estamos trazendo um „list‟ de objetos. Neste exemplo.$values. ?> <select name="id_funcionario"> <?php require('uses/funcionario_. } public function abrir(){ $this->db = mysql_connect($this->local. Importamos as classes banco e funcionario. $db = new Banco(). private $senha. $this->msg0 = 'Conexão falou. É extremamente parecido com o artigo anterior. Faremos aqui uma combo (HTML) básica.$this->db) or die($this->msg1). public function __construct(){ $this->local = 'localhost'. private $db. passando os filtros. private $msg0.$this>user. caso houvesse necessidade. $this->user = 'root'. estamos querendo trazer todos os funcionários existente na base. Agora vamos entrar na classe do banco e entender. erro: '. } .

$qtd = count($fields_where). }//garante que o where entre caso tenha algum parametro $sql . $tb_name.' = '." from ". $values_where ){ $qtd = count($fields_where).' = '. $db = new Banco().= ' where '. Erro: Quantidade de campos diferente da quantidade de valores'). if ($qtd >= 1 ) { for ($j=1.$campo. $linha = mysql_fetch_array($res).$j++){ if ($j == 1) { $sql .= ' WHERE '. </script> <?php }else{ // Monta a string SQL===================== $sql = "select ". if ($qtd != count($values_where)){ // verifica o numero de fields e values ?> <script language="javascript"> alert('Função: selectDataDb.$tb_name." FROM ". $fields_where. $fields_where. com os parametros enviados (podendo ser nenhum ou vários) }//else }//public function public function selectDatasDb( $tb_name. if ($j<$qtd ) { $sql . $closed = NULL.= $fields_where[$j].mysql_error()). }//garante que o where entre caso tenha algum parametro $sql .$obj[1].public function fechar(){ //analisar se o mysql_close precisa ser colocado numa variável $closed = mysql_close($this->db). // <Monta a string SQL> ===================== $sql = "SELECT id_".mysql_error()). $db->abrir(). valores(values) da consulta $obj = explode('_'. } public function BuscaValor( $campo. return $linha[$campo]. } } } //==================== </Monta a string SQL> $query = mysql_query($sql) or die ($sql .$tb_name).$tb_name. $h = 0.= ' AND '. $values_where){ // nome da tabela. // inicializamos a variável . if ($j<$qtd ) { $sql .= ' and '.$j<=$qtd.$values_where[$j]. if ($qtd != 0 ) { for ($j=1. } } } //======================================= $res = mysql_query($sql) or die ($sql .$j++){ if ($j == 1) { $sql . vetores: campos(fields).$values_where[$j].$j<=$qtd. // retorna o valor do campo especifico.= $fields_where[$j].

$tb_name. e por aí vai. Ao acessar a função selectDatasDb().$fields_where. da classe. return $new_objeto. $i++) { $fields_name = mysql_field_name($fields.. Vamos entender. minha classe tem que entender qual objeto será carregado após o select no banco. A função selectDatasDb() recebe os parâmetros enviados pela função PegarTodos em FuncionarioDAO.// Laço que trará TODOS os objetos já alimentados while ($linha = mysql_fetch_array($query)){ $objDTO = new $obj[1]. $new_objeto = new $obj[1]..). para só então. e colhemos o id de cada um. //chamamos o próximo objeto } //fecha o while.$obj[1]. no momento sendo apenas um DTO. Sabemos que ao acessar o banco..$tb_name). $db->fechar().. $i < $columns. é automático. Nisso tornamos genérica nossa classe. Sendo assim. // informa os fields/campos da tabela do banco $columns = mysql_num_fields($fields). nas demais partes do sistema (nome do objeto. $fields_where[$qtd+1] = 'id_'. $fields = mysql_list_fields('db_exitosites'.(eu fiz alguns comentários no código. $i). precisamos „criar‟ um objeto de retorno de dados (obedecendo ao Data Access Object). //retorna todos os objetos populados } ?> Ok! Aqui está a tão temida classe. e posteriormente popular o objeto: .$tb_name). para só então colhermos os fields e seus valores. $fields_values = $this>BuscaValor(mysql_field_name($fields. //Aqui declaramos um novo objeto que é clone de nosso DAO.. //conta o número de campos $new_objeto[$h] = clone $objDTO. $values_where[$qtd+1] = $linha[$fields_where[$qtd+1]]. E sabendo que o objeto carrega em si o nome da própria tabela a que se refere. terminando nosso vetor de objetos. Não se assuste pelo tamanho e pela quantidade de laços de repetição (mais do que do artigo anterior)..$values_where). talvez ajude). for ($i = 0. $i). $new_objeto[$h]->$fields_name = $fields_values. } $h += 1. $obj = explode('_'. Qualquer objeto pode ser carregado. Como fazer minha função entender qual objeto o banco irá popular? Agora vai a importância de manter a nomenclatura da tabela do nosso banco. Aqui montaremos nosso select para saber os registros (linhas) que existem no banco. Simples assim! Nenhuma novidade. o nome da tabela é „quebrada‟ (ultizando o „explode‟ do php). o sistema entender qual objeto será carregado.

E é aqui que fica a construção de nossa SQL Dinâmica. $fields_values = $this->BuscaValor( mysql_field_name( $fields.contato. $i++) { $fields_name = mysql_field_name($fields. contato: 3.$values_where).' = '. } Para buscar o valor. }//garante que o where entre caso tenha algum parametro $sql . $i). Buscar o nome é simples. que nós determinamos no while: while ($linha = mysql_fetch_array($query)){ então „varremos‟ os dados de cada linha. Que populará a quantidade de objetos referente às tublas da tabela no banco. //aqui populamos com todos os campos e valores o objeto.$obj[1].sexo‟. utilizaremos a função do mysql: mysql_field_name. //conta o número de campos $new_objeto[$h] = clone $objDTO.endereco. Para entender melhor: se numa tabela eu tenho „nome. } } } //==================== </Monta a string SQL> Após isso. e assim sucessivamente. // informa os fields/campos da tabela do banco $columns = mysql_num_fields($fields). endereco: 2.$j++){ if ($j == 1) { $sql . if ($qtd >= 1 ) { for ($j=1.$values_where[$j]. nome seria a posição: 1. Afinal precisamos dizer qual registro precisamos obter.$tb_name). for ($i = 0. precisaremos de uma função de auxílio.$j<=$qtd. Desta vez o nosso „for‟ ficará dentro de outro laço de repetição „while‟. no momento sendo apenas um DTO. $fields = mysql_list_fields('db_exitosites'.$tb_name.$fields_where. . o nome da tabela. $i < $columns. Senão o código fica muito complicado. enquanto houver registro no banco (linhas ou tuplas).$tb_name." FROM ". e passamos por parâmetro o id colhido no select acima: $fields_where[$qtd+1] = 'id_'.$obj[1].// <Monta a string SQL> ===================== $sql = "SELECT id_". //Aqui declaramos um novo objeto que é clone de nosso DAO. $new_objeto[$h]->$fields_name = $fields_values.= ' WHERE '.= $fields_where[$j]. e os vetores que construirão nossas wheres. $i). lembrando que alimentamos mais uma vez os fields e os values dinamicamente. $values_where[$qtd+1] = $linha[$fields_where[$qtd+1]]. if ($j<$qtd ) { $sql .= ' AND '. Conforme já explicado ! Envia-se o nome do campo desejado. Onde informamos a posição da Field.

É só substituir o nomes que costumamente é usando nos SQL de consulta.$this->BuscaValor(mysql_field_name($fields. por variáveis que receberão os valores em tempo de execução. O próximo IF é somente para concatenar a palavra „and‟ à string citada. $i).= $fields_where[$j]. //retorna todos os objetos populados .$j<=$qtd. fechamos o banco e retornamos o vetor com todos os objetos populados: $db->fechar(). Nenhum segredo até então. O IF garante que nossa where receberá algo para ser trabalhado. trazendo TODOS os que fora passados. } } } //======================================= A variável $sql recebe o texto concatenado com os novos valores das variáveis. A modificação (entre trazer um objeto ou um vetor com todos os objetos) aqui é apenas dentro do „SelectDatasDb‟. if ($qtd != count($values_where)){ // verifica o numero de fields e values ?> <script language="javascript"> alert('Função: selectDataDb. return $new_objeto.$fields_where.= ' where '.$values_where).$tb_name.$j++){ if ($j == 1) { $sql . if ($j<$qtd ) { $sql . Quantas cláusulas formarão a where? É necessário saber." from ". Entraremos então na função BuscaValor. E nisso consiste a idéia principal do artigo. para concluir os processos. Erro: Quantidade de campos diferente da quantidade de valores').' = '. O primeiro IF depois do For. até a quantidade de campos e valores existe no vetor. </script> <?php }else{ Caso esteja tudo ok. $qtd = count($fields_where).$tb_name. garante que o a palavra „where‟ seja concatenada na string $sql.= ' and '. if ($qtd != 0 ) { for ($j=1. Logo na entrada cuidaremos de nosso filtro do select.$values_where[$j]. e logo após é concatenado os campos e valores respectivamente. } //garante que o where entre caso tenha algum parâmetro $sql . e já tratamos isso logo no início.$campo. caso haja mais campos e valores a serem concatenados. // Monta a string SQL===================== $sql = "select ". Prosseguimos para a construção real do select. Validamos se a quantidade de fields e seus valores correspondem no IF abaixo. O laço de repetição varre o vetor. A função 'BuscaValor' é idêntica a utilizada na função do artigo anterior. que varre todos os registros existentes no banco. que traz apenas um objeto populado. Ainda dentro do „SelectDatasDb‟.

fun_data'. E mais uma vez. deixei as classes CRUD dentro do objeto de conexão com o banco. não usufruí de alguns conceitos OO (herança. ou seja. 4ª Parte: Update criado por Marcio Alexandre em 02/04/2012 5:12pm Hellow Comunidade! Depois de quase dois anos após a implementação dos códigos. overinding. agradeço a atenção. para cada objeto temos a estrutura que receberá cada dado referente à sua tabela no banco. este objeto tem um estrutura semelhando à tabela do banco. e confecção do primeiro artigo sobre CRUD Genérico em PHP. Por questão de organização e segurança. . e numa forma de comunicação nada trivial. o objetivo aqui é outro! Mas.php). aqui estou!!! Vamos comentar sobre o Update do assunto abordado no título. desde já. =) O Desempenho aqui deve cair. corrijam em seus códigos. talvez. na hora da manutenção não precisamos cair nas funções dento do objeto do banco. Talvez tenha ficado algo ainda mais confuso. =) Tornarei a repetir algumas conceitos teóricos. devido ao tamanho. enfim. e espero ter contribuído com mais este conhecimento à comunidade OO PHP. 'fun_nome. Encerro aqui mais este artigo. E nos objetos (DAO) nós importaremos as classe e alimentamos os parâmetros (aqui estará o segredo de manipulação das wheres). alerto que por inexperiência. quem tiver os conceitos solidificados. Percebam que a „regra de negócio‟ fica numa camada muito acima. Bom. = = 'tb_funcionario'. =) CRUD Genéricos em PHP.. mas factível. para deixar os artigos independentes. sou Marcio Alexandre. já no padrão de acesso às classes genéricas: class funcionario{ private $nome_tabela private $camposInsert var $id_funcionario. Vamos lá. Bom pessoal. overload. Qualquer dúvida. interface). Próximo artigo: Update.Pronto! Um pouco complexo. Como já sabemos. abstract. mas temos uma grande vantagem.. Basta nos preocupar com o carregamento do objeto desejado e à alimentação dos vetores que farão as 'wheres'. é só entrar em contato. trazendo o código referente a um funcionário (funcionarioDAO.

bastando informar campo e valor. public function setDados($id_funcionario.} public function PegarTodos($fields. Utilizaremos.} public function getNome() { return $this->fun_nome. serão os funcionários. com os quais filtraríamos nossos dados no banco (refiro-me à where). portanto. o que teremos é uma lista de objetos sendo exibida na tela (no caso. $this->fun_data = $fun_data . „$fields‟ e „$values‟ que seriam vetores que trazem os campos e seus valores. alteramos o que achamos necessário."'. public function getNomeCampos() { return $this->camposInsert. e a outra trazendo os fields (campos).$db){ $db->DeleteDataDb($this>getNomeTabela(). respectivamente.$fields.$this->fun_data. uma que traz o nome da tabela no banco. } public function getDataBr() { /*modelo brasil (00/00/0000 00:00)*/ $temp = explode(' '. }else{$this->id_funcionario = null.' '. Pergunta provável: Como o banco vai saber qual tupla atualizar. } public function Atualizar($objeto. e poderia ser 01 ou mais filtros.$temp_data[1]. $data = $temp_data[2].'/'."' ". Tudo deve ser analisado. inclusive segurança.$values. } } public function Salvar($objeto. } public function getNomeTabela() { return $this->nome_tabela.$values). $hora = $temp[1].$hora .$values. Também inserimos duas funções para trazer os valores dessas duas variáveis. no objeto. Estraríamos aqui um dos pontos principais dos artigos anteriores. } public function getValorCampos() { return "'". } } Observe que adicionamos mais duas variáveis privadas. pois sendo assim. Após carregar nosso objeto. var $fun_data.$db){ $db->insertObjectToDB($objeto).$fields. Neste artigo não precisamos abordar os campos e seus valores.$this>fun_nome.$fun_nome.$values).$db){ return $db>selectDatasDb($this->getNomeTabela().$temp[0]). e o retornamos para a função “Atualizar” da classe “funcionário”.'/'. Basicamente. return $data. nas camadas superiores a função „Atualizar‟.var $fun_nome.$temp_data[0]. $temp_data = explode(''. $fields.$values. conforme já entendemos no segundo artigo desta série). } public function getId(){ return $this->id_funcionario.$fun_data){ if (isset($id_funcionario)){ $this->id_funcionario = $id_funcionario .$values).$db){ $db>updateObjectToDB($objeto). } public function Deletar($fields. } $this->fun_nome = $fun_nome . a where poderia ser determinada pelo desenvolvedor sem problemas.'". } public function Pegar($fields.$db){ return $db>selectDataDb($this->getNomeTabela(). onde está o id? Ao ser exibida a lista de funcionários. para exemplificar) e ao clicar em uma opção. o link para alterá-lo deverá enviar o id do objeto . nos vetores. } public function getDataEn() { return $this->fun_data. em sequência como utilizamos nos inserts em sql. carregaremos de imediato aquele objeto (utilizando a função “Pegar”. Nos artigos anteriores eu expliquei os parâmetos.$this->fun_data). exibimos os dados no HTML.

?>"> </td> <td> </td> </tr> <tr> <td> </td> <td><input type="submit" name="Submit" value="Atualizar"></td> </tr> <tr> <td> </td> <td> </td> </tr> </table> </form> Caso submeta o formulário.$msg. ?>"> <input type="hidden" name="fun_data" id="fun_data" value="<?php echo $objeto->getDataEn(). Feito isso. Para tornar toda estrutura o mais dinâmico possível: // mensagem que informará se foi atualizado. uma vez que é dado o refresh $msg = @$_REQUEST['msg']. $qtd = count($link).'</font><br><br>'.$values. ?>" method="post"> <table width="50%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="17%">Nome</td> <td width="49%"><input name="txtNome" type="text" id="txtNome" value="<?php echo $objeto->getNome().php'). $values[1] = $_REQUEST['id']. echo '<br>'. Muito simples de se entender. ?>"></td> </tr> <tr> <td> <input type="hidden" name="id_funcionario" id="id_funcionario" value="<?php echo $objeto->getId(). $db = new Banco(). inicializamos o formulário de atualização: <form action="<?php echo $link[$qtd-1]. //Instancio minha classe funcionario require('uses/funcionario_. $fun = new funcionario(). onde tem minhas funções genéricas require('uses/banco. //Aqui digo que se não for um ‘post’. ou enviar via „hidden‟. então é para exibir os dados do funcionário escolhido if (!$_POST){ //verifica se é uma submissão de formulário ou não // recebo o id do funcionario $fields[1] = 'id_funcionario'. } //captura do link da página para que o refresh seja automático $link = explode('/'.$_SERVER ['REQUEST_URI']).$db). teríamos a seguinte estrutura: //instancio o banco. $objeto = $fun->Pegar($fields.escolhido. os dados serão processados (refresh): . concorda? Na página de exibição dos dados a serem alterados. if (isset($msg)){ echo '<font color="red"> '.php').

Um brecha aqui para futuras melhorias. $fun->fun_nome = $fun_nome. a função/método „Atualizar‟ da classe Funcionario. As explicações vem no código.$objeto>getNomeTabela()). enfim.. $temp_valores = explode('.href='index.'. no que se refere à nomenclatura $temp_campos = explode('.catch.. $qtd_campos = count($temp_campos). }else{ ?> <script language="javascript"> alert('Identificador do conteúdo não especificado').. </script> <?php } // else do if (!isset($id_funcionario) . // Aqui teremos os nomes dos campos da tabela. possibilidades são inúmeras)...$objeto>getNomeCampos()). ### Updater public function updateObjectToDB($objeto){ //15abr2010 // Processando. } // else do if (!$_POST){ ?> Como vimos nos artigos anteriores. para não perder no quesito processo. $fun_data = $_POST['fun_data']. a critério do programador. Como não haverá retorno (o que poderia. Aqui é válido informar que há uma padronização no banco de dados em todas as tabelas. enviando o objeto já populado. correspondendo a algum critério de controle de try .php'.$objeto>getValorCampos()).vamos ao coração deste artigo! Vamos entrar na classe do banco e entender. e é de fácil entendimento considerando o nome intuitivo dos métodos.$temp_id[1].'.<?php }else{ //buscando os dados REQUEST $id_funcionario = $_POST['id_funcionario']. evoca o método „updateObjectToDB‟do banco enviado. conforme foi alimentado no objeto.$db). //MONTANDO STRING SQL Dinamicamente------------------- . //inserindo no objeto $fun->id_funcionario = $id_funcionario. // Novos dados (ou não) que serão substituidos no banco. Pronto! Entendido estas arestas que não tratei na época. //chamando função para envio dos dados dinâmicamente $fun->Atualizar($fun. $fun->fun_data = $fun_data.. if (!isset($id_funcionario) || $id_funcionario != ''){ $fun_nome = $_POST['txtNome'] . trazer um true ou false. $id_nome = 'id_'. location. por mais que os dados novos e antigos sejam os mesmos. Vale lembrar que todos os campos serão substituído. a obtenção de dados do objeto passado! $temp_id = explode('_'. //criando variável que será representará o id do objeto passado. em execução. afim de nortear a criação dinâmica da string SQL. //Variável que armazenará a qtd de campos.

break.mysql_error()).' '.php?id='. Acredito que com esta despretensiosa solução. que trabalhe com open source. //Redirecionando para página de atualização referida header('Location:'.= '. e vice-versa. ou seja. que prefiram trabalhar com SQL Dinâmicas.$temp_valores[$i]. for ($i=0. // caso queria imprimir a string SQL para algum teste (e somente para isto). podemos atender melhor (quesito: tempo) a gerencia de requisitos e sua manipulação. * Estou pensando em hospedar estes codes em algum site controlador de versões. e não fazer mais 'n' funções para gerenciar o fluxo de dados entre o banco e a aplicação.' set '. if ($i < $qtd_campos-1){ $new_string .''. //---------------------------------------------------//echo $new_string. baseada em collections (arrays). esta camada CRUD. juntos.'_update. Isto pode facilitar muito a vida de alguns analistas/programadores.= ' WHERE '.' = '. $sql = $new_string. $query = mysql_query($sql) or die ($sql. //abre o banco submete à mysql_query e fecha $db = new Banco(). a intenção é somente esta. . é isso!! Espero que seja útil à comunidade.$temp_id[1].$objeto->getNomeTabela(). $db->fechar(). } } // concatena a SQL com a cláusula where. de maneira simples e segura.$objeto>getId().'&msg=Atualizado').$ objeto->getId().'. atendendo inclusive aos conceitos de "metodologias agéis".$id_nome. pois TODA aplicação estaria em cima de cinco funções somente.$i++){ // concatenação de valores $new_string . } Bom. desabilitar. $new_string .' = '.$i <= $qtd_campos-1.------------$new_string = 'UPDATE '. $db->abrir(). seria rápida e facilmente gerenciável. qualquer alteração ou nova implementação.= $temp_campos[$i]. A ideia é construímos.