CRUD Genéricos em PHP. 1ª Parte: Create
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:
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):
Simples assim, a classe recebe via parâmetro o objeto que quer inserir no banco. A string SQL é montada automaticamente de acordo com os dados que já existem no objeto (neste caso sem wheres, mas nos próximos artigos mostraremos como montar as strings SQL com 1 ou mais wheres).
E com os próprios dados que vem do objeto, obedecendo os padrões de nomenclaturas adotados previamento já direciona para próxima página após a inserção.
Agora o mais simples, o formulário de inserção:
Portanto, instanciamos o $func, onde alimentamos o objeto com os dados fornecidos pelo formulário, e depois salvamos enviando ele mesmo ($func) e a instância do objeto do banco ($db), via parâmetro.
Só para clarear, utilizamos o $_SERVER ['REQUEST_URI'] para dar o refresh automático, para não precisar se preocupar com mais este campo do formulário, deixando mais dinâmico.
Bom, é isso aí, espero ter contribuído com uma programação mais prática e sem frameworks pesados e muitas vezes desnecessários.
Até a 2ª Parte...
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); } }
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 = 'localhost'; $this->user = 'root'; $this->senha = ''; $this->msg0 = 'Conexão falou, erro: '.mysql_error(); $this->msg1 = 'Não foi possível selecionar o banco de dados!'; $this->nome_db = 'db_sistemaqualquer'; } public function abrir(){ $this->db = mysql_connect($this->local,$this->user,$this->senha) or die($this->msg0); mysql_select_db($this->nome_db,$this->db) or die($this->msg1); } public function fechar(){ //analisar se o mysql_close precisa ser colocado numa variável $closed = mysql_close($this->db); $closed = NULL; } public function insertObjectToDB($objeto){ $db = new Banco(); $db->abrir(); $sql = "INSERT INTO ".$objeto->getNomeTabela()."(".$objeto->getNomeCampos().") VALUES ( ".$objeto->getValorCampos().")"; $query = mysql_query($sql) or die ($sql.' '.mysql_error()); $db->fechar(); unset($objeto); $temp_id = explode('_',$objeto->getNomeTabela()); header('location: '.$temp_id[1].'.php?msg=Inserido'); } } //class
E com os próprios dados que vem do objeto, obedecendo os padrões de nomenclaturas adotados previamento já direciona para próxima página após a inserção.
Agora o mais simples, o formulário de inserção:
<html> <head> <title>Cadastro de Funcionário</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> </head> <body> <?php if (!$_POST){ $msg = @$_REQUEST['msg']; if (isset($msg)){ echo '<font color="red"> '.$msg.'</font><br><br>'; } $link = explode('/',$_SERVER ['REQUEST_URI']); $qtd = count($link); echo '<br>'; ?> <form action="<?php echo $link[$qtd-1]; ?>" 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> <tr> <td> </td> <td> </td> </tr> </table> </form> <?php }else{ require('uses/banco.php'); $db = new Banco(); require('uses/funcionarioDAO.php'); $fun_nome = $_POST['txtNome']; $fun_data = date('Y-m-d H:i:s'); $func = new funcionario(); $func->setDados(null,$fun_nome,$fun_data); $func->salvar($func,$db); } ?> </body> </html>
Portanto, instanciamos o $func, onde alimentamos o objeto com os dados fornecidos pelo formulário, e depois salvamos enviando ele mesmo ($func) e a instância do objeto do banco ($db), via parâmetro.
Só para clarear, utilizamos o $_SERVER ['REQUEST_URI'] para dar o refresh automático, para não precisar se preocupar com mais este campo do formulário, deixando mais dinâmico.
Bom, é isso aí, espero ter contribuído com uma programação mais prática e sem frameworks pesados e muitas vezes desnecessários.
Até a 2ª Parte...
Obrigado pela contribuição, Victor Azevedo.
Esse artigo postei há uns 3 anos, quando eu engatinhava no php. Mts melhorias já forma sugeridas, aqui mesmo. Dá uma lida, e sucesso!!
Esse artigo postei há uns 3 anos, quando eu engatinhava no php. Mts melhorias já forma sugeridas, aqui mesmo. Dá uma lida, e sucesso!!
28/08/2013 7:33am
(~11 anos atrás)
Meus parabéns. Acho que pra melhorar, deve-se usar PDO e blocos try catch no CRUD.
Segue um pequeno exemplo da implantação do PDO e tratamento de erro.
try{
$stmte = $pdo->prepare("INSERT INTO cliente(idcliente, nome) VALUES (?, ?)");
$stmte->bindParam(1, $codigo);
$stmte->bindParam(2, $nome);
$executa = $stmte->execute();
if($executa){
echo 'Dados inseridos com sucesso';
}
else{
throw new Exception();
}
}
catch(Exception$e){
echo $e->getMessage();
}
Segue um pequeno exemplo da implantação do PDO e tratamento de erro.
try{
$stmte = $pdo->prepare("INSERT INTO cliente(idcliente, nome) VALUES (?, ?)");
$stmte->bindParam(1, $codigo);
$stmte->bindParam(2, $nome);
$executa = $stmte->execute();
if($executa){
echo 'Dados inseridos com sucesso';
}
else{
throw new Exception();
}
}
catch(Exception$e){
echo $e->getMessage();
}
28/08/2013 7:19am
(~11 anos atrás)
Teu código ta show, eu só alteraria poucas coisas como utilizar o operador ternário ?.
Ao invés de :
if (isset($id_funcionario)){ $this->id_funcionario = $id_funcionario ; }else{$this->id_funcionario = null; }
eu usaria:
$this->id_funcionario = (isset($id_funcionario)) ? $id_funcionario : null;
Ao invés de :
if (isset($id_funcionario)){ $this->id_funcionario = $id_funcionario ; }else{$this->id_funcionario = null; }
eu usaria:
$this->id_funcionario = (isset($id_funcionario)) ? $id_funcionario : null;
03/12/2012 8:22am
(~12 anos atrás)
percebe-se que dedução não é o seu forte!
=)
Olhando a classe, fica fácil... lição de casa, ok?! ;)
=)
Olhando a classe, fica fácil... lição de casa, ok?! ;)
06/07/2012 8:46pm
(~12 anos atrás)
Como é que você quer que a gente salve se vc não nos deu a estrutura do banco de dados?
06/07/2012 8:45pm
(~12 anos atrás)
Como é que você quer que a gente salve se vc não nos deu a estrutura do banco de dados?
06/07/2012 8:17pm
(~12 anos atrás)
Mazza,
Todos os meus projetos faço utilizando este prática. Portanto, são vários e vários...
A diferença é que hoje utilizo interfaces e classes abstratas, e logicamente um conceito OO mais interessante.
Todos os meus projetos faço utilizando este prática. Portanto, são vários e vários...
A diferença é que hoje utilizo interfaces e classes abstratas, e logicamente um conceito OO mais interessante.
25/01/2012 12:51pm
(~12 anos atrás)
http://colour-switch.com