0% acharam este documento útil (0 voto)
7 visualizações16 páginas

PHP:: Pdo - Crud Completo: Introdução

Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
7 visualizações16 páginas

PHP:: Pdo - Crud Completo: Introdução

Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 16

PHP:: PDO – CRUD COMPLETO

Fonte: https://alexandrebbarbosa.wordpress.com/2016/09/04/php-pdo-crud-completo/

Introdução
Em outros artigos sobre persistência, já abrangi sobre CRUD utilizando inclusive alguns padrões de projetos
mas não eram aplicações completas. Entretanto, imagino que para quem está iniciando a programar em PHP e ainda
não está acostumado a padrões de projetos, poderá estar com inúmeras dúvidas e precisa de algo simples, porém
funcional. Por isso, decidi, criar este artigo que abrange de forma simples o CRUD em PHP fazendo uso do banco de
dados MySQL. CRUD é um acrônimo para as quatro operações do Banco: CREATE (Criar), READ (Ler), Update
(Atualizar) e DELETE (Excluir). Quando você cria uma aplicação que conte com todas estas operações, está
desenvolvendo um CRUD.
Vamos então passa a passo, etapa por etapa entendendo como fazer uma aplicação CRUD (agenda de
contatos) desde a conexão com banco de dados. Queri deixar claro que é importe se acostumar a programar conforme
o paradigma Orientado a Objetos. Você até pode programar conforme o paradigma procedural, mas estará limitado em
alguns aspectos e até irá se deparar com outros problemas que somente terão solução pela Orientação a Objetos. Não
entraremos em detalhes sobre isso aqui. Além disso, é importante que você tenha noções da linguagem SQL a fim de
ter um melhor aproveitamento.

Primeira etapa: Criando o banco de dados


Precisamos de um banco de dados e elegemos o MySQL como SGDB para gerenciá-lo. Vamos criar uma
agenda de contatos, com três colunas nome, e-mail e telefone.
1- Para criar o banco de dados execute o código:
CREATE DATABASE crudsimples DEFAULT CHARACTER SET utf8 DEFAULT COLLATE
utf8_general_ci;
2- Em seguida selecione o banco:
USE crudsimples;
3- Então crie a tabela contatos:
CREATE TABLE contatos (
id INT NOT NULL AUTO_INCREMENT,
nome VARCHAR(45) NOT NULL,
email VARCHAR(45) NOT NULL,
celular VARCHAR(15) DEFAULT NULL,
PRIMARY KEY(id)
);

Segunda etapa: Conexão com banco de dados


Não é novidade que atualmente se adotou a classe PDO, uma interface de conexão, que permite criar a
abstração com o sistema de banco de dados. Sendo assim, vamos criando nosso objeto de conexão PDO.
Nesta etapa, vamos iniciar o projeto por criar um novo arquivo com extensão “.php” e, obviamente aqui o nome
do arquivo é livre, ou seja, você poderá dar o nome de sua preferência . Além disso, é claro, utilize a IDE de sua
preferência ou até um editor de textos se assim preferir. Então como já foi dito, inicie com um arquivo limpo, e digitando
apenas as tags de abertura e encerramento do php “<?php” e “?>”. Além disso, você pode pular algumas linhas entre
elas para facilitar a digitação do código. Após isso, já estará apto para digitar os primeiros códigos entre as tags do
php, e inicie esse trabalho por criar um bloco “try e cacth” onde, vamos instanciar o objeto de conexão com o banco de
dados: PDO.
<?php

try {
$conexao = new PDO("mysql:host=localhost;dbname=crudsimples;charset=utf8mb4",
"root", "123456", [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
} catch (PDOException $erro) {
echo "Erro na conexão: " . $erro->getMessage();
}
Note como que instanciamos o objeto PDO, sua sintaxe é:
<objeto PDO> = new PDO(String <Nome da fonte de dados>, String <usuário do
banco>, String <senha do banco>);

Note que o objeto que será associado a variável $conexão será do tipo PDO, um objeto que representa a
conexão com o banco e que será o nosso manipulador.
Como parâmetros, o construtor da classe exige:
• uma DSN (Nome da fonte de dados), onde informamos o driver do banco, o nome do host e o nome
do banco de dados e note que são separados por ponte e vírgula. Mas a DSN suporta diferentes
métodos de argumentação. Caso tenha interesse dê uma olhada na documentação
(http://php.net/manual/pt_BR/pdo.construct.php)
• um nome de usuário para conexão com o banco de dados
• a senha para o usuário informado.
Opcionalmente é possível passar um array associativo com opções de conexão, como um terceiro parâmetro,
mas não vou abranger aqui.
Observação: deste momento em diante, não darei tanta ênfase as tags de abertura e fechamento do bloco de
códigos php. Serão mencionadas apenas quando for necessário misturar código php com tags html ou adicionar em
outro local no arquivo.
Perceba que o parâmetro de catch foi informado como um argumento do tipo PDOExecption. Esta classe do
php estende RuntimeException e é específica para representar os erros gerados pela classe PDO. Para termos uma
representação mais específica, a classe PDO nos apresenta um método setAttribute para o objeto PDO, note os blocos
acima reescritos com o método, logo abaixo:
try {
$conexao = new PDO("mysql:host=localhost; dbname=crudsimples", "root", "123456");
$conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $erro) {
echo "Erro na conexão:" . $erro->getMessage();
}

O método setAttribute() nos permite adicionar atributos no objeto de conexão, sua sintaxe:
<valor boleano> = setAttribute(inteiro “Atributo”, misto “Valor”);
Note que o método devolve um valor booleano como resposta e assim você pode descobrir se tudo correu
bem. Ainda, como atributos, há um do tipo inteiro e outro que pode ser de vários tipos. No caso do argumento inteiro,
este método deve receber algum dos atributos válidos para o objeto de conexão. Estes objetos são representados por
constantes, semelhantes a esta que estamos usando aí acima. Se você estiver interessado em saber quais são, veja
a documentação: http://php.net/manual/pt_BR/pdo.setattribute.php. Por hora vamos
utilizar PDO::ATTR_ERRMODE que indica como relatar o erro. Entenda que o segundo argumento deve ser compatível
com o primeiro. No caso de PDO::ATTR_ERRMODE, espera-se receber um dos três modos disponíveis:
PDO::ERRMODE_SILENT: Só defina o código de erro
PDO::ERRMODE_WARNING: gerar um E_WARNING.
PDO::ERRMODE_EXCEPTION: Lance uma exceção.
Atento a isto, descobrimos que a última opção é a melhor por estarmos trabalhando com uma PDOException no
nosso bloco catch. Sendo assim, agora será possível imprimir uma exceção lançada, por chamar o
método getMessage() da PDOException. É exatamente isso que estamos fazendo dentro do bloco catch, como você
pode ter notado.
Pois bem, será que já terminamos a parte de conexão? Talvez, mas poderemos melhorar algo aqui: lembre-se
que estamos no Brasil, onde é comum utilizar acentos e, por isso, a codificação comum é UTF-8. Como é que
informamos isso ao servidor de banco de dados? Note os blocos try e catch reescritos e terminados:
try {
$conexao = new PDO("mysql:host=localhost; dbname=crudsimples", "root",
"123456");
$conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conexao->exec("set names utf8");
} catch (PDOException $erro) {
echo "Erro na conexão:" . $erro->getMessage();
}
O que mudou? Foi adicionado uma linha com o método exec() da classe PDO, que executar uma instrução
SQL e retornar o número de linhas afetadas. Neste caso, não esperamos nenhum retorno, mas queremos executar a
instrução SQL direto no banco. Note que esta não é uma instrução da classe PDO e sim do banco de dados. Caso
queira saber mais a respeito desta instrução no MySQL, consulte http://dev.mysql.com/doc/refman/5.7/en/charset-
connection.html
Muito bem, terminado a segunda etapa de construção da aplicação, a próxima será criar um formulário simples
e inserir dados nele, construindo assim a primeira função do CRUD.

Terceira Etapa: Criando um formulário


Precisamos de um formulário, então vamos criá-lo por inserir este código HTML bem abaixo do código php que
já criamos com a conexão. Lembre-se antes de fechar a tag PHP com um “?>” antes de inserir as tags seguintes, se
você já não o fez.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Agenda de contatos</title>
</head>
<body>
<form action="?act=save" method="POST" name="form1" >
<h1>Agenda de contatos</h1>
<hr>
<input type="hidden" name="id" />
Nome:
<input type="text" name="nome" />
E-mail:
<input type="text" name="email" />
Celular:
<input type="text" name="celular" />
<input type="submit" value="salvar" />
<input type="reset" value="Novo" />
<hr>
</form>
</body>
</html>
Até aqui, se você abrir a página, vai ver o nosso formulário com 3 campos e dois botões, mas ainda não
funciona.

Veja que também utilizamos uma tag input do tipo “hidden” e esta será utilizada para o recurso de Update.
Visto que, já que mencionei o “Update”, vamos já preparar nosso formulário para a função este recurso. Então, dentro
de cada tag input, antes do encerramento “/>”, vamos acrescentar um espaço e adicionar um código php para
preenchimento automático. Este código, naturalmente deverá estar delimitado pelas tags do php “<?php” e “?>”. Então,
leve o cursor até a área informada acima e adicione o código entre as tags do php. Ele deverá ser assim:
<html>
<head>
<meta charset="UTF-8">
<title>Agenda de contatos</title>
</head>
<body>
<form action="?act=save" method="POST" name="form1" >
<h1>Agenda de contatos</h1>
<hr>
<input type="hidden" name="id" <?php
// Preenche o id no campo id com um valor "value"
if (isset($id) && $id != null || $id != "") {
echo "value=\"{$id}\"";
}
?> />
Nome:
<input type="text" name="nome" <?php
// Preenche o nome no campo nome com um valor "value"
if (isset($nome) && $nome != null || $nome != ""){
echo "value=\"{$nome}\"";
}
?> />
E-mail:
<input type="text" name="email" <?php
// Preenche o email no campo email com um valor "value"
if (isset($email) && $email != null || $email != ""){
echo "value=\"{$email}\"";
}
?> />
Celular:
<input type="text" name="celular" <?php
// Preenche o celular no campo celular com um valor "value"
if (isset($celular) && $celular != null || $celular != ""){
echo "value=\"{$celular}\"";
}
?> />
<input type="submit" value="salvar" />
<input type="reset" value="Novo" />
<hr>
</form>
</body>
</html>

Novamente, até aqui se você abrir a página no browser, ainda não vai acontecer porque estas instruções de
decisão apenas estão verificando se uma variável foi definida e se seu valor é diferente de nulo ou diferente de vazio.
Todavia, as variáveis ainda não foram definidas e por isso nada acontece. Mas vamos adicionar estas novas instruções
antes do bloco “try e catch” na primeira parte do nosso código, ou seja, ficará logo depois da primeira tag de abertura
do php “<?php” do início e antes do bloco “try e catch”:
<?php
// Verificar se foi enviando dados via POST
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$id = (isset($_POST["id"]) && $_POST["id"] != null) ? $_POST["id"] : "";
$nome = (isset($_POST["nome"]) && $_POST["nome"] != null) ? $_POST["nome"] : "";
$email = (isset($_POST["email"]) && $_POST["email"] != null) ? $_POST["email"] :
"";
$celular = (isset($_POST["celular"]) && $_POST["celular"] != null) ?
$_POST["celular"] : NULL;
} else if (!isset($id)) {
// Se não se não foi setado nenhum valor para variável $id
$id = (isset($_GET["id"]) && $_GET["id"] != null) ? $_GET["id"] : "";
$nome = NULL;
$email = NULL;
$celular = NULL;
}
Agora, se você executar a página, poderá preencher o formulário e notar uma diferença ao clicar em “Salvar”.
A diferença é quando clicar no botão “Salvar” e fazer o “submit”, pois, os dados permanecerão nos campos como se
nada acontecesse.
Como assim? Esta é a nossa intenção neste momento, porque definimos e preenchemos as variáveis via
POST, aquelas que são verificadas no código dentro das tags input dentro do formulário. Mesmo com refresh da página,
os dados não sumirão, mas continuarão lá. Precisamos agora salvar estes dados no banco de dados e assim alcançar
nosso primeiro objetivo. Esta é a nossa próxima etapa: Create! Você deve ter notado também que estamos trabalhando
com uma variável $id, embora esta variável ainda não receba nenhum valor. Não se preocupe logo voltaremos nossa
atenção a ela.

Quarta Etapa: Create – salvando novo registro no banco de dados


Nosso formulário contém dados que precisam ser persistidos no banco de dados. Para isso funcionar, vamos
adicionar o código após a ultima chave que encerra o “try e catch” criado para a conexão. Ah, há mais um detalhe aqui
que reforço: Estamos trabalhando no primeiro bloco de comandos php, então vamos inserir o seguinte código logo
abaixo do “try e catch” de conexão. A frase foi repetida para reforçar a atenção! O código é este:
if (isset($_REQUEST["act"]) && $_REQUEST["act"] == "save" && $nome != "") {
try {
$stmt = $conexao->prepare("INSERT INTO contatos (nome, email, celular) VALUES
(?, ?, ?)");
$stmt->bindParam(1, $nome);
$stmt->bindParam(2, $email);
$stmt->bindParam(3, $celular);

if ($stmt->execute()) {
if ($stmt->rowCount() > 0) {
echo "Dados cadastrados com sucesso!";
$id = null;
$nome = null;
$email = null;
$celular = null;
} else {
echo "Erro ao tentar efetivar cadastro";
}
} else {
throw new PDOException("Erro: Não foi possível executar a declaração
sql");
}
} catch (PDOException $erro) {
echo "Erro: " . $erro->getMessage();
}
}

Muito bem! se você rodar este código e clicar em salvar, as informações vão ser escritas no banco de dados e
o formulário não retornará com mais nenhum valor.Além disso, uma mensagem “Dados cadastrados com sucesso!”
será apresentada logo acima do formulário:
Agora note na próxima imagem que os dados podem ser recuperados no Banco de dados:

Vamos entender o que foi feito até aqui:


Primeiro, note que iniciamos um bloco “if” para descobrir se há uma ação “act” para salvar “save”, se sim, então
entra em um novo bloco try e catch. Neste bloco try e catch, utilizamos o objeto de conexão do PDO que está associado
a variável $conexao. Assim, temos a nossa disposição alguns métodos do objeto PDO para atender as nossas
necessidade. O primeiro método é o prepare(), note a linha:

$stmt = $conexao->prepare("INSERT INTO contatos (nome, email, celular) VALUES (?, ?,


?)");

Este método transforma uma declaração SQL na forma de um “objeto declaração” que pode ser
manipulado por alguns métodos específicos. Entre estes métodos, o bindParam() que vincula uma variável a um
espaço demarcado na declaração.
$stmt->bindParam(1, $nome);
$stmt->bindParam(2, $email);
$stmt->bindParam(3, $celular);

O método bindParam() recebe ainda outros argumentos, mas não vamos abrangê-los aqui. Se desejar
descobrir mais sobre isso, não deixe de conferir a documentação do
php: http://php.net/manual/pt_BR/pdostatement.bindparam.php
Qual a diferença entre bindParam e bindValue?
No bindParam() o argumento esperado é uma referência (variável ou constante) e não pode ser um tipo
primitivo como uma string ou número solto, retorno de função/método. Já bindValue() pode receber referências e
valores como argumento.
$stmt->bindParam(':v1', 10); // Inválido
$stmt->bindParam(':v1', getValor()); // Inválido
Diferenças em PDOStatement::execute()
Com bindParam, ao contrário de bindValue, a variável está vinculada com uma referência e só será avaliada
no momento que PDOStatement::execute() é chamado.
Com bindParam:
$sex = 'male';
$s = $dbh->prepare('SELECT name FROM students WHERE sex = :sex');
$s->bindParam(':sex', $sex);
$sex = 'female';
$s->execute(); // Executado quando $sex = 'female'
Com bindValue:
$sex = 'male';
$s = $dbh->prepare('SELECT name FROM students WHERE sex = :sex');
$s->bindValue(':sex', $sex);
$sex = 'female';
$s->execute(); // Executado quando $sex = 'male'
A declaração estando pronta, ou seja, o novo objeto PDO Statement, então poderá ser executada. Neste
momento que chamamos o método execute() do próprio objeto Statement:

if ($stmt->execute()) {
Você até poderia deixar de usar o método bindParam e definir as variáveis dentro de um array passando-os
como argumento diretamente ao método execute(), todavia isto será valido apenas para tipos String. Além disso, você
também poderia colocar a variável diretamente na declaração recebida pelo método prepare(), mas estaria vulnerável
a problemas de segurança que também não vou destacar neste artigo. Em resumo, procure sempre usar
o bindParam().
Ainda, veja que chamamos o método execute() dentro de um bloco “if”, pois ele retornará um valor booleano
true se a instrução for executada com êxito. E por isso, temos um recurso para darmos o início ao tratamento de erros.
Visando refinar esse tratamento de erros, aproveitamos para fazer uso de mais um método da PDO Statement que fica
disponível após o execute, que é o rowCount():
if ($stmt->rowCount() > 0) {
O rowCount() retornará o número de linhas afetadas na tabela por uma última instrução DELETE, INSERT ou
UPDATE executada pelo objeto PDOStatement correspondente. Em nosso caso, até agora foi um INSERT. Já que
estamos inserindo uma linha, esperamos que como resposta haja um número maior que zero “0”. Logo, temos uma
segunda etapa para tratar erros que nos permite fazer mais alguma coisa em caso de êxito ou não. E é isso que
acontece:
Primeiro, imprimimos uma mensagem informando que tudo correu bem:
echo "Dados cadastrados com sucesso!";

Em seguida, limpamos as variáveis para que o formulário não seja preenchido novamente nesta etapa:
$id = null;
$nome = null;
$email = null;
$celular = null;

Concluímos a etapa Create do CRUD. Agora vamos passar para próxima etapa que é o Read.

Quinta Etapa: Read – Lendo os registros no banco


A funcionalidade “Read” pode ser construída de algumas maneiras: por usar um filtro para ler um registro por
vez e em seguida o apresentar na tela ou mesmo utilizar algum filtro para ler vários registros e listá-los na tela, ou
ainda, chamando uma listagem inteira por trazer todos os registros de uma tabela. Vamos chamar uma listagem inteira,
embora isto seja verdade apenas de forma acadêmica. Vamos seguir adiante, criando uma tabela html com a tag table.
Você deve posicionar esta tag table logo depois da tag de fechamento do formulário “</form>” que criamos dentro das
tags “<body>” e “</body>” em nosso html e antes da tag de fechamento “</body>”. Este é o código:
<table border="1" width="100%">
<tr>
<th>Nome</th>
<th>E-mail</th>
<th>Celular</th>
<th>Ações</th>
</tr>
</table>

Se você abrir a página, vai perceber apenas o cabeçalho da tabela, mas nada é impresso abaixo dele e esta é
nossa intenção até este momento.

Mas, agora vamos então gerar uma listagem dos registros abaixo deste cabeçalho e para isso, você deverá
abrir e fechar as tags do php “<?php” e “?>” logo abaixo da tag de fechamento da linha da tabela “</tr>” e, antes da tag
de fechamento da tabela “</table>”. Dentro deste bloco de código php, precisamos adicionar um novo bloco “try e
catch”:

<?php
try {

$stmt = $conexao->prepare("SELECT * FROM contatos");

if ($stmt->execute()) {
while ($rs = $stmt->fetch(PDO::FETCH_OBJ)) {
echo "<tr>";
echo "<td>".$rs->nome."</td><td>".$rs->email."</td><td>".$rs->celular
."</td><td><center><a href=\"\">[Alterar]</a>"
."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
."<a href=\"\">[Excluir]</a></center></td>";
echo "</tr>";
}
} else {
echo "Erro: Não foi possível recuperar os dados do banco de dados";
}
} catch (PDOException $erro) {
echo "Erro: ".$erro->getMessage();
}
?>

Dentro da tabela entre as tags “<table>” e “</table>”, ficará assim:


<table border="1" width="100%">
<tr>
<th>Nome</th>
<th>E-mail</th>
<th>Celular</th>
<th>Ações</th>
</tr>
<?php
// Bloco que realiza o papel do Read - recupera os dados e apresenta na tela
try {
$stmt = $conexao->prepare("SELECT * FROM contatos");
if ($stmt->execute()) {
while ($rs = $stmt->fetch(PDO::FETCH_OBJ)) {
echo "<tr>";
echo "<td>".$rs->nome."</td><td>".$rs->email."</td><td>".$rs-
>celular
."</td><td><center><a href=\"\">[Alterar]</a>"
."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
."<a href=\"\">[Excluir]</a></center></td>";
echo "</tr>";
}
} else {
echo "Erro: Não foi possível recuperar os dados do banco de dados";
}
} catch (PDOException $erro) {
echo "Erro: ".$erro->getMessage();
}
?>
</table>

Abrindo a página, você perceberá que já é possivel ver um registro salvo anteriormente. Criamos este registro
no teste da quarta etapa.

O que foi feito lá no código inserido?


Notou que preparamos mais uma declaração com o método prepare()? Sim, é exatamente para convertermos
nossa declaração SQL em um objeto PDO Statement. Depois disto, logo utilizamos o método execute() do objeto PDO
Statement mas, desta vez, não precisamos informar nenhum parâmetro e por isso não utilizamos o
método bindParam(). Mas se fôssemos utilizar um filtro, seria ideal utilizar o método bindParam(), como já dito
anteriormente. Na próxima etapa, vamos precisar construir um “Read” desta forma e você irá compreender o porquê.
Depois de executar o método execute(), precisamos recuperar o resultado de alguma forma, então iterar sobre
cada registro resultante e apresentá-lo na tela. Por isso, criamos uma variável $rs de “result set” que receberá a cada
iteração de loop como sendo um objeto de registro. O método fetch() do novo objeto “result set”, “busca” o resultado
obtido pelo método execute() de PDO Statement. Perceba que um argumento é passado ao método fetch,
o PDO::FETCH_OBJ, a fim de informar ao método que queremos obter os registros como objetos. O loop utiliza a
função while, que talvez você já tenha entendido o motivo, entretanto, apenas para ficar claro, aqui estamos informamos
que as iterações deverão continuar enquanto um valor seja verdadeiro para while. Enquanto for possível iterar pelo
“result set”, será verdadeiro. Assim, dentro do bloco while poderemos nos referir ao objeto em $rs por seus atributos.
Mas, que atributos são estes? São os nomes das colunas na tabela contatos do banco de dados. Então, isso se torna
interessante porque trabalhar com um registro de forma orientado a objetos tornam os nossos projetos bem mais
interessantes. É claro que você pode iterar o “result set” e trabalhar com array, assim como as antigas técnicas e se
desejar saber mais sobre isso leia mais sobre isso, consulte a documentação do php
em http://php.net/manual/pt_BR/pdostatement.fetch.php. Entretanto, se estiver criando um sistema totalmente
orientado a objetos, o ideal será manipular os resultados como objetos.
Uma vez sabendo como recuperar o valor de cada coluna de um “result set”, é fácil imprimi-los na tela e
fazemos isso simplesmente com o construtor de linguagem “echo”, como foi visto nas linhas seguintes:
echo "<tr>";
echo "<td>".$rs->nome."</td><td>".$rs->email."</td><td>".$rs->celular
."</td><td><center><a href=\"\">[Alterar]</a>"
."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
."<a href=\"\">[Excluir]</a></center></td>";
echo "</tr>";
Sexta Etapa: Update – alterando registros salvos no banco.
Até aqui, você deve ter notado que ao trabalhar com a classe PDO seguimos um certo padrão e por isso,
adicionar os recursos finais ao nosso aplicativo, será relativamente fácil a você compreender, mesmo agora antes de
implementá-los. Note que já deixamos previamente preparados dois links para cada registo que são impressos na
tabela html, que apresenta nossos registros. Mas estes links não possuem uma âncora para nenhum lugar. Se você
clicar sobre eles, não farão absolutamente nada. Faremos uso do primeiro link para implementar o “Update” mas nada
tão complexo assim. Para começar, precisamos informar um filtro logo alí, qual registro será que queremos alterar.
Então, logo nos lembramos que para cada registro, temos um campo numérico e que é a chave primária do mesmo.
Este campo é o id. Além disso, precisamos nos lembrar que nossa aplicação tendenciosamente decide tudo no “refresh
de tela”, assim precisaremos indicar uma ação “act” que será interpretada neste momento. Por isso, volte sua atenção
para estas linhas:
echo "<td>".$rs->nome."</td><td>".$rs->email."</td><td>".$rs->celular
."</td><td><center><a href=\"\">[Alterar]</a>"
."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
."<a href=\"\">[Excluir]</a></center></td>";
Dentro da tag “<a>” com rótulo a frente “[Alterar]”, preencha ente as duas “aspas escapadas” (\”) a seguinte
informação:

?act=upd&id=" . $rs->id . "

Difícil? Não, não é! Note o que muda:


echo "<td>".$rs->nome."</td><td>".$rs->email."</td><td>".$rs->celular
."</td><td><center><a href=\"?act=upd&id=" . $rs->id . "\">[Alterar]</a>"
."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
."<a href=\"\">[Excluir]</a></center></td>";

O que fizemos alí foi indicar na âncora “href” do link os parâmetros “act” e “id” que serão lidos pela mesma
página no refresh. Note também que não indicamos uma página alvo para âncora e sim apenas deixamos o sinal de
interrogação “?”. Se você abrir a página no navegador e levar ponteiro acima do link “Alterar” de cada registro, vai notar
na barra de status inferior do browser que agora um link é informado. Além disso, também já apresenta o id para cada
registro. Já que estamos mexendo alí, podemos também já deixar pronto o outro link para “Delete”. Então, no dentro
da tag “<a>” com rótulo “[Excluir]” logo a frente, preencha ente as duas “aspas escapadas” (\”) a seguinte informação:

?act=del&id=" . $rs->id . "


Veja agora o que muda:
echo "<td>".$rs->nome."</td><td>".$rs->email."</td><td>".$rs->celular
."</td><td><center><a href=\"?act=upd&id=" . $rs->id . "\">[Alterar]</a>"
."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
."<a href=\"?act=del&id=" . $rs->id . "\">[Excluir]</a></center></td>";
echo "</tr>";
O que fizemos alí, também foi indicar na âncora do link os parâmetros “act” e “id” que serão lidos pela mesma
página no refresh. Novamente, se você abrir a página no navegador e levar ponteiro até o link “Excluir” de cada registro,
vai notar na barra de status inferior do browser que agora também há um link sendo informado. Além disso, já apresenta
o id para cada registro.
Certo, até aqui preparamos o nosso aplicativo para receber os novos recursos que precisam ser
implementados. Na verdade, apenas a parte de interação com o usuário está pronta, mas não a sua funcionalidade.
Então vamos a lógica!
Para alterar um registro, precisamos primeiro recuperar este registro no formulário para dar ao usuário
exatamente o registro salvo. E então como faremos isso? Você se lembra das variáveis $id, $nome, $email e $celular?
Sim, estas variáveis precisam receber os dados filtrados para preencherem o formulário. Então vamos fazer o seguinte:
logo após o final do bloco “if” que foi criado lá na quarta etapa “Create”, ou seja, o bloco que faz a persistência dos
dados (Lembra-se?), será necessário adicionar este novo bloco “if” logo abaixo:
if (isset($_REQUEST["act"]) && $_REQUEST["act"] == "upd" && $id != "") {
try {
$stmt = $conexao->prepare("SELECT * FROM contatos WHERE id = ?");
$stmt->bindParam(1, $id, PDO::PARAM_INT);
if ($stmt->execute()) {
$rs = $stmt->fetch(PDO::FETCH_OBJ);
$id = $rs->id;
$nome = $rs->nome;
$email = $rs->email;
$celular = $rs->celular;
} else {
throw new PDOException("Erro: Não foi possível executar a declaração
sql");
}
} catch (PDOException $erro) {
echo "Erro: ".$erro->getMessage();
}
}
Mais uma vez, quando você abrir a página novamente e clicar no Update, note que os dados daquele registro
serão recuperados no formulário, semelhante ao início, quando estavamos enviando via POST para testar o
preenchimento do formulário. A diferença desta vez é o processo dos dados serem recuperados não de uma origem
via POST, mas agora diretamente do banco de dados.

Percebeu lá no código que inserimos agora que este bloco “if” também é muito semelhante a aquele anterior
na quinta etapa onde listamos os registros na tabela? Sim, mas com duas diferenças sutis:
Primeira: Utilizamos um filtro na instrução SQL pelo id e novamente fazemos uso do bindParam() para adicioná-
lo ao objeto PDO Statement. Além disso, também informamos agora mais um novo parâmetro no método bindParam(),
que informa qual é o tipo de dado na variável $id. Este parâmetro é indicado pela constante PDO::PARAM_INT.
Segunda: Não utilizamos mais o laço de repetição While! E isso faz sentido aqui, pois se estamos filtrando pela
coluna chave primária, esperamos é claro recuperar apenas um único registro.
Na sequencia, são recuperados os atributos do “result set” para cada variável correspondente, que são lidas
logo em seguida durante a construção do formulário. Assim, os campos são preenchidos com os dados das variáveis,
“alimentado-os com os valores” em “value”. Interessante?
Ok mas, recuperamos os dados no formulário, alteramos e … e agora para salvar os dados atualizados
novamente no banco? Porque se você clicar no botão salvar, o resultado será um novo registro logo abaixo:
Falhamos em nosso projeto? Precisamos adicionar mais um botão para “Update“? Claro que não! Mas fica
evidente que precisamos fazer uma alteração na lógica para atender a nova funcionalidade. Afinal, os nossos objetivos
anteriores estavam sendo alcançados, mas agora estamos em uma nova etapa!
Esta mudança será feita no bloco “if” que criamos na Quarta Etapa: Create. Então, esteja antento as mudanças
seguintes:
Primeiro, olhe atentamente a linha abaixo:
$stmt = $conexao->prepare("INSERT INTO contatos (nome, email, celular) VALUES (?, ?,
?)");
Coloque esta linha dentro do bloco “else” de um novo bloco “if” que criaremos para fazer teste da variável $id,
para checar se a mesma recebeu algum valor. O quê? Sim, desta forma:
if ($id != "") {

} else {
$stmt = $conexao->prepare("INSERT INTO contatos (nome, email, celular) VALUES (?,
?, ?)");
}
Muito bem! então, alí a decisão recai sobre condição em que, se a variável $id estiver vazia, será feito um
Insert, comojá estava sendo feito antes. Mas e se a variável $id possuir um valor diferente de vazio?
Neste caso, faremos um “Update”! Aqui está a grande sacada! Então, o bloco deverá receber uma nova
preparação de declaração para “Update”, fincando portando, assim:
if ($id != "") {
$stmt = $conexao->prepare("UPDATE contatos SET nome=?, email=?, celular=? WHERE id
= ?");
$stmt->bindParam(4, $id);
} else {
$stmt = $conexao->prepare("INSERT INTO contatos (nome, email, celular) VALUES (?,
?, ?)");
}
Notou que, caso seja recebido um valor em $id, estaremos executando um “UPDATE” para aquele valor
armazenado na variável $id?
Além disso, como vamos lidar com um quarto parâmetro a ser inserido no objeto PDO Statement, ele também
já o é informado logo na linha abaixo da instrução contendo o método prepare(), dentro do mesmo do bloco “if”:
$stmt->bindParam(4, $id);
Agora a aplicação está funcionando como esperado! Já é possível criar novos registros e atualizá-los! Faça o
teste!

Sétima Etapa: Delete – Excluíndo registros do banco de dados

Você já deve estar se amarrando em tudo isso até aqui!


Mas ainda falta um recurso para concluirmos nosso projeto do CRUD: Delete. Se você foi acompanhando o
passo a passo e testando o aplicativo, neste momento já deve contar com um monte de registros que pensa em excluir:

Você deve se lembrar de que na etapa anterior, preparamos a interface com usuário, deixando basicamente
pronto o Link de exclusão de registro, se lembra? Portanto, falta apenas implementar a funcionalidade para este link!
Para isso, logo abaixo do ultimo bloco “if” e antes da tag de encerramento do primiero bloco php “?>” e que se localiza
antes das tags html, inclua este novo bloco if:
if (isset($_REQUEST["act"]) && $_REQUEST["act"] == "del" && $id != "") {
try {
$stmt = $conexao->prepare("DELETE FROM contatos WHERE id = ?");
$stmt->bindParam(1, $id, PDO::PARAM_INT);
if ($stmt->execute()) {
echo "Registo foi excluído com êxito";
$id = null;
} else {
throw new PDOException("Erro: Não foi possível executar a declaração
sql");
}
} catch (PDOException $erro) {
echo "Erro: ".$erro->getMessage();
}
}
Veja que estes códigos já se tornaram muito familiares, mas com certas semelhanças e sutis diferenças:
Primeira observação: nossa declaração é um Delete e recebe um parâmetro id que será associado ao objeto
PDO Statement utilizando o método bindParam(), novamente com o novo parâmetro PDO::PARAM_INT.
Segunda observação: agora não utilizamos mais um método fetch() para “juntar” alguma coisa, mas apenas o
método execute(). Sim, é muito óbvio o motivo disso: porque não precisamos recuperar nenhum valor mas apenas
executar o método execute() que já o é suficiente para cumprir o objetivo.
Perceba que dentro do bloco “if” do método execute() acima, deixamos uma instrução para imprimir na tela
uma mensagem, informando que o registro foi excluído com êxito. Além disso, após a exclusão, precisamos anular
qualquer valor na variável $id, para que o nosso formulário retorne livre e pronto para receber novos registros. Se você
iniciar a página no browser, verá que o recurso de exclusão agora também funciona perfeitamente!

Segurança
Para reforçar a segurança, especialmente em tratamento de senhas e entrada de usuários, aqui estão algumas
mudanças recomendadas:

Armazenamento de senhas: Use password_hash() para criptografar senhas antes de armazená-las no banco.
Validação de entrada: Utilize filter_var() para sanitizar e validar dados antes de inseri-los no banco.

Exemplo de validação e armazenamento seguro de senha:

1. <?php
2. $senha = "minhaSenha123";
3. $senhaSegura = password_hash($senha, PASSWORD_DEFAULT);
4. ?>
5.

E para validar um e-mail:

1. <?php
2. $email = "[email protected]";
3. if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
4. echo "E-mail inválido!";
5. }
6. ?>
7.

Conclusão
Pronto! Agora temos um CRUD completo, contendo as quatro operações do banco de dados em
funcionamento: Create, Read, Update e Delete! Acredito que por seguir este passo a passo a risca, lendo e relendo se
for o caso, você estará apto a criar aplicações com CRUD. Poderá criar até outras aplicações mais complexas do que
esta deste artigo!
Dica importante: Nunca
recomendo que você seja forte
seguidor do uso das teclas
CTRL+C e CTRL+V quando
está aprendendo, mas o ideal é
ir digitando caractere a
caractere! Todavia, se preferir
fazê-lo a fim de conferir a
funcionalidade do código, a
decisão está em suas mãos!
have a fun!

<?php
/**
* Projeto de aplicação CRUD utilizando PDO - Agenda de Contatos
*
* Alexandre Bezerra Barbosa
*/

// Verificar se foi enviando dados via POST


if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$id = (isset($_POST["id"]) && $_POST["id"] != null) ? $_POST["id"] : "";
$nome = (isset($_POST["nome"]) && $_POST["nome"] != null) ? $_POST["nome"] : "";
$email = (isset($_POST["email"]) && $_POST["email"] != null) ? $_POST["email"] :
"";
$celular = (isset($_POST["celular"]) && $_POST["celular"] != null) ?
$_POST["celular"] : NULL;
} else if (!isset($id)) {
// Se não se não foi setado nenhum valor para variável $id
$id = (isset($_GET["id"]) && $_GET["id"] != null) ? $_GET["id"] : "";
$nome = NULL;
$email = NULL;
$celular = NULL;
}

// Cria a conexão com o banco de dados


try {
$conexao = new PDO("mysql:host=localhost;dbname=crudsimples", "root", "123456");
$conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conexao->exec("set names utf8");
} catch (PDOException $erro) {
echo "Erro na conexão:".$erro->getMessage();
}

// Bloco If que Salva os dados no Banco - atua como Create e Update


if (isset($_REQUEST["act"]) && $_REQUEST["act"] == "save" && $nome != "") {
try {
if ($id != "") {
$stmt = $conexao->prepare("UPDATE contatos SET nome=?, email=?, celular=?
WHERE id = ?");
$stmt->bindParam(4, $id);
} else {
$stmt = $conexao->prepare("INSERT INTO contatos (nome, email, celular)
VALUES (?, ?, ?)");
}
$stmt->bindParam(1, $nome);
$stmt->bindParam(2, $email);
$stmt->bindParam(3, $celular);

if ($stmt->execute()) {
if ($stmt->rowCount() > 0) {
echo "Dados cadastrados com sucesso!";
$id = null;
$nome = null;
$email = null;
$celular = null;
} else {
echo "Erro ao tentar efetivar cadastro";
}
} else {
throw new PDOException("Erro: Não foi possível executar a declaração
sql");
}
} catch (PDOException $erro) {
echo "Erro: ".$erro->getMessage();
}
}

// Bloco if que recupera as informações no formulário, etapa utilizada pelo Update


if (isset($_REQUEST["act"]) && $_REQUEST["act"] == "upd" && $id != "") {
try {
$stmt = $conexao->prepare("SELECT * FROM contatos WHERE id = ?");
$stmt->bindParam(1, $id, PDO::PARAM_INT);
if ($stmt->execute()) {
$rs = $stmt->fetch(PDO::FETCH_OBJ);
$id = $rs->id;
$nome = $rs->nome;
$email = $rs->email;
$celular = $rs->celular;
} else {
throw new PDOException("Erro: Não foi possível executar a declaração
sql");
}
} catch (PDOException $erro) {
echo "Erro: ".$erro->getMessage();
}
}

// Bloco if utilizado pela etapa Delete


if (isset($_REQUEST["act"]) && $_REQUEST["act"] == "del" && $id != "") {
try {
$stmt = $conexao->prepare("DELETE FROM contatos WHERE id = ?");
$stmt->bindParam(1, $id, PDO::PARAM_INT);
if ($stmt->execute()) {
echo "Registo foi excluído com êxito";
$id = null;
} else {
throw new PDOException("Erro: Não foi possível executar a declaração
sql");
}
} catch (PDOException $erro) {
echo "Erro: ".$erro->getMessage();
}
}?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Agenda de contatos</title>
</head>
<body>
<form action="?act=save" method="POST" name="form1" >
<h1>Agenda de contatos</h1>
<hr>
<input type="hidden" name="id" <?php

// Preenche o id no campo id com um valor "value"


if (isset($id) && $id != null || $id != "") {
echo "value=\"{$id}\"";
}
?> />
Nome:
<input type="text" name="nome" <?php

// Preenche o nome no campo nome com um valor "value"


if (isset($nome) && $nome != null || $nome != "") {
echo "value=\"{$nome}\"";
}
?> />
E-mail:
<input type="text" name="email" <?php

// Preenche o email no campo email com um valor "value"


if (isset($email) && $email != null || $email != "") {
echo "value=\"{$email}\"";
}
?> />
Celular:
<input type="text" name="celular" <?php

// Preenche o celular no campo celular com um valor "value"


if (isset($celular) && $celular != null || $celular != "") {
echo "value=\"{$celular}\"";
}
?> />
<input type="submit" value="salvar" />
<input type="reset" value="Novo" />
<hr>
</form>
<table border="1" width="100%">
<tr>
<th>Nome</th>
<th>E-mail</th>
<th>Celular</th>
<th>Ações</th>
</tr>
<?php
// Bloco que realiza o papel do Read - recupera os dados e apresenta
na tela
try {
$stmt = $conexao->prepare("SELECT * FROM contatos");
if ($stmt->execute()) {
while ($rs = $stmt->fetch(PDO::FETCH_OBJ)) {
echo "<tr>";
echo "<td>".$rs->nome."</td><td>".$rs-
>email."</td><td>".$rs->celular
."</td><td><center><a href=\"?act=upd&id=".$rs-
>id."\">[Alterar]</a>"
."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
."<a href=\"?act=del&id=".$rs-
>id."\">[Excluir]</a></center></td>";
echo "</tr>";
}
} else {
echo "Erro: Não foi possível recuperar os dados do banco de
dados";
}
} catch (PDOException $erro) {
echo "Erro: ".$erro->getMessage();
}
?>
</table>
</body>
</html>

Você também pode gostar