Exclusão – Sistema de Cadastro com PHP + PDO e MySQL
Olá pessoal, hoje vamos finalizar a série de posts sobre sistema de cadastro com PHP + PDO e MySQL, vou demonstrar como efetuar a exclusão de clientes cadastrados no banco de dados.
Nesse sistema quando excluirmos um cliente e o mesmo possuir uma foto gravada, será necessário excluir essa foto da pasta para manter a organização senão com o tempo teremos várias imagens sem “cliente” ocupando espaço no servidor.
Para construir a exclusão foi necessário adicionar mais uma função no script “custom.js” e mais uma condição para excluir no script “action_cliente.php“.
Outros posts que podem interessar:
Consulta – Sistema de Cadastro com PHP + PDO e MySQL
Inclusão – Sistema de Cadastro com PHP + PDO e MySQL
Edição – Sistema de Cadastro com PHP + PDO e MySQL
Vou postar o script do banco de dados como foi feito nos posts anteriores.
Script do Banco de Dados
Estrutura da tabela não foi alterada.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
CREATE DATABASE IF NOT EXISTS db_blog; USE db_blog; CREATE TABLE tab_clientes( id integer auto_increment primary key, nome varchar(100), cpf varchar(20), email varchar(50), telefone varchar(20), celular varchar(20), data_nascimento date, status varchar(10), foto varchar(200), data_cadastro timestamp default CURRENT_TIMESTAMP, data_alteracao timestamp ); |
Script JavaScript para Validação, Máscaras, Load de Imagem
No script “custom.js” foi adicionado uma função “confirmaExclusao(id)” que será disparada sempre que for pressionado o link “Excluir”, esse evento foi atribuído via JavaScript “addEventListener()”.
Editado 21/11/2015: O loop para atribuição da função confirmaExclusao(id) ao evento “click” foi alterado, existe um problema quando atribuímos funções anônimas para eventos no javascript, para solucionar é necessário sempre trabalhar com funções nomeadas e ainda fazer um ajuste no escopo do contador “i” dentro do loop, mais detalhes nesse link.
Essa função exibe uma mensagem confirmando se o usuário deseja mesmo excluir esse cliente, poderíamos usar os “alerts()” do bootstrap mas seria necessário jQuery, mas nessa série de posts usamos somente JavaScript puro.
Caso seja confirmada exclusão é criado um formulário dinamicamente no DOM com inputs contendo a ação “excluir” e o id do cliente que será excluído, capturo o id do cliente lendo o atributo “rel” do link “Excluir”, o formulário será enviado via POST para o script “action_cliente.php“.
Observem que seria mais prático enviar a ação e o id do cliente via GET no próprio link, mas no começo dessa série de posts já defini que o script “action_cliente.php” só receberia requisições via POST como uma das medidas de segurança.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
/* Atribui ao evento submit do formulário a função de validação de dados */ var form = document.getElementById("form-contato"); if (form != null && form.addEventListener) { form.addEventListener("submit", validaCadastro); } else if (form != null && form.attachEvent) { form.attachEvent("onsubmit", validaCadastro); } /* Atribui ao evento keypress do input cpf a função para formatar o CPF */ var inputCPF = document.getElementById("cpf"); if (inputCPF != null && inputCPF.addEventListener) { inputCPF.addEventListener("keypress", function(){mascaraTexto(this, '###.###.###-##')}); } else if (inputCPF != null && inputCPF.attachEvent) { inputCPF.attachEvent("onkeypress", function(){mascaraTexto(this, '###.###.###-##')}); } /* Atribui ao evento keypress do input data de nascimento a função para formatar o data (dd/mm/yyyy) */ var inputDataNascimento = document.getElementById("data_nascimento"); if (inputDataNascimento != null && inputDataNascimento.addEventListener) { inputDataNascimento.addEventListener("keypress", function(){mascaraTexto(this, '##/##/####')}); } else if (inputDataNascimento != null && inputDataNascimento.attachEvent) { inputDataNascimento.attachEvent("onkeypress", function(){mascaraTexto(this, '##/##/####')}); } /* Atribui ao evento keypress do input telefone a função para formatar o Telefone (00 0000-0000) */ var inputTelefone = document.getElementById("telefone"); if (inputTelefone != null && inputTelefone.addEventListener) { inputTelefone.addEventListener("keypress", function(){mascaraTexto(this, '## ####-####')}); } else if (inputTelefone != null && inputTelefone.attachEvent) { inputTelefone.attachEvent("onkeypress", function(){mascaraTexto(this, '## ####-####')}); } /* Atribui ao evento keypress do input celular a função para formatar o Celular (00 00000-0000) */ var inputCelular = document.getElementById("celular"); if (inputCelular != null && inputCelular.addEventListener) { inputCelular.addEventListener("keypress", function(){mascaraTexto(this, '## #####-####')}); } else if (inputCelular != null && inputCelular.attachEvent) { inputCelular.attachEvent("onkeypress", function(){mascaraTexto(this, '## #####-####')}); } /* Atribui ao evento change do input FILE para upload da foto*/ var inputFile = document.getElementById("foto"); var foto_cliente = document.getElementById("foto-cliente"); if (inputFile != null && inputFile.addEventListener) { inputFile.addEventListener("change", function(){loadFoto(this, foto_cliente)}); } else if (inputFile != null && inputFile.attachEvent) { inputFile.attachEvent("onchange", function(){loadFoto(this, foto_cliente)}); } /* Atribui ao evento click do link de exclusão na página de consulta a função confirmaExclusao */ var linkExclusao = document.querySelectorAll(".link_exclusao"); if (linkExclusao != null) { for ( var i = ; i < linkExclusao.length; i++ ) { (function(i){ var id_cliente = linkExclusao[i].getAttribute('rel'); if (linkExclusao[i].addEventListener){ linkExclusao[i].addEventListener("click", function(){confirmaExclusao(id_cliente);}); }else if (linkExclusao[i].attachEvent) { linkExclusao[i].attachEvent("onclick", function(){confirmaExclusao(id_cliente);}); } })(i); } } /* Função para validar os dados antes da submissão dos dados */ function validaCadastro(evt){ var nome = document.getElementById('nome'); var email = document.getElementById('email'); var cpf = document.getElementById('cpf'); var status = document.getElementById('status'); var data_nascimento = document.getElementById('data_nascimento'); var telefone = document.getElementById('telefone'); var celular = document.getElementById('celular'); var filtro = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i; var contErro = ; /* Validação do campo nome */ caixa_nome = document.querySelector('.msg-nome'); if(nome.value == ""){ caixa_nome.innerHTML = "Favor preencher o Nome"; caixa_nome.style.display = 'block'; contErro += 1; }else{ caixa_nome.style.display = 'none'; } /* Validação do campo email */ caixa_email = document.querySelector('.msg-email'); if(email.value == ""){ caixa_email.innerHTML = "Favor preencher o E-mail"; caixa_email.style.display = 'block'; contErro += 1; }else if(filtro.test(email.value)){ caixa_email.style.display = 'none'; }else{ caixa_email.innerHTML = "Formato do E-mail inválido"; caixa_email.style.display = 'block'; contErro += 1; } /* Validação do campo cpf */ caixa_data = document.querySelector('.msg-data'); if(data_nascimento.value == ""){ caixa_data.innerHTML = "Favor preencher a Data de Nascimento"; caixa_data.style.display = 'block'; contErro += 1; }else{ caixa_data.style.display = 'none'; } /* Validação do campo cpf */ caixa_cpf = document.querySelector('.msg-cpf'); if(cpf.value == ""){ caixa_cpf.innerHTML = "Favor preencher o CPF"; caixa_cpf.style.display = 'block'; contErro += 1; }else{ caixa_cpf.style.display = 'none'; } /* Validação do campo telefone */ caixa_telefone = document.querySelector('.msg-telefone'); if(telefone.value == ""){ caixa_telefone.innerHTML = "Favor preencher o Telefone"; caixa_telefone.style.display = 'block'; contErro += 1; }else{ caixa_telefone.style.display = 'none'; } /* Validação do campo celular */ caixa_celular = document.querySelector('.msg-celular'); if(celular.value == ""){ caixa_celular.innerHTML = "Favor preencher o Celular"; caixa_celular.style.display = 'block'; contErro += 1; }else{ caixa_celular.style.display = 'none'; } /* Validação do campo status */ caixa_status = document.querySelector('.msg-status'); if(status.value == ""){ caixa_status.innerHTML = "Favor preencher o Status"; caixa_status.style.display = 'block'; contErro += 1; }else{ caixa_status.style.display = 'none'; } if(contErro > ){ evt.preventDefault(); } } /* Função para formatar dados conforme parâmetro enviado, CPF, DATA, TELEFONE e CELULAR */ function mascaraTexto(t, mask){ var i = t.value.length; var saida = mask.substring(1,); var texto = mask.substring(i); if (texto.substring(,1) != saida){ t.value += texto.substring(,1); } } /* Função para exibir a imagem selecionada no input file na tag <img> */ function loadFoto(file, img){ if (file.files && file.files[]) { var reader = new FileReader(); reader.onload = function (e) { img.src = e.target.result; } reader.readAsDataURL(file.files[]); } } /* Função para exibir um alert confirmando a exclusão do registro*/ function confirmaExclusao(id){ retorno = confirm("Deseja excluir esse Registro?") if (retorno){ //Cria um formulário var formulario = document.createElement("form"); formulario.action = "action_cliente.php"; formulario.method = "post"; // Cria os inputs e adiciona ao formulário var inputAcao = document.createElement("input"); inputAcao.type = "hidden"; inputAcao.value = "excluir"; inputAcao.name = "acao"; formulario.appendChild(inputAcao); var inputId = document.createElement("input"); inputId.type = "hidden"; inputId.value = id; inputId.name = "id"; formulario.appendChild(inputId); //Adiciona o formulário ao corpo do documento document.body.appendChild(formulario); //Envia o formulário formulario.submit(); } } |
Script PHP para Exclusão do Dados
Como já vem ocorrendo nos outros posts, adicionei a condição para verificar a ação solicitada “if ($acao == ‘excluir’):“, ação e o id do cliente estão sendo enviados via POST pelo formulário com JavaScript.
Com esses dados basta executar um SELECT na tabela de clientes para capturar o nome da foto, com isso podemos excluir se ela for diferente de “padrao.jpg“, pois não tem sentido excluir a foto padrão. Se o cliente possuir foto excluímos o arquivo da pasta e posteriormente executamos a instrução DELETE para exclusão do registro no banco de dados.
Após a confirmação da exclusão será exibida a mensagem de sucesso e após 3 segundos o usuário será redirecionado para página com a listagem de clientes “index.php“.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sistema de Cadastro</title> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="css/custom.css"> </head> <body> <div class='container box-mensagem-crud'> <?php require 'conexao.php'; // Atribui uma conexão PDO $conexao = conexao::getInstance(); // Recebe os dados enviados pela submissão $acao = (isset($_POST['acao'])) ? $_POST['acao'] : ''; $id = (isset($_POST['id'])) ? $_POST['id'] : ''; $nome = (isset($_POST['nome'])) ? $_POST['nome'] : ''; $cpf = (isset($_POST['cpf'])) ? str_replace(array('.','-'), '', $_POST['cpf']): ''; $email = (isset($_POST['email'])) ? $_POST['email'] : ''; $foto_atual = (isset($_POST['foto_atual'])) ? $_POST['foto_atual'] : ''; $data_nascimento = (isset($_POST['data_nascimento'])) ? $_POST['data_nascimento'] : ''; $telefone = (isset($_POST['telefone'])) ? str_replace(array('-', ' '), '', $_POST['telefone']) : ''; $celular = (isset($_POST['celular'])) ? str_replace(array('-', ' '), '', $_POST['celular']) : ''; $status = (isset($_POST['status'])) ? $_POST['status'] : ''; // Valida os dados recebidos $mensagem = ''; if ($acao == 'editar' && $id == ''): $mensagem .= '<li>ID do registros desconhecido.</li>'; endif; // Se for ação diferente de excluir valida os dados obrigatórios if ($acao != 'excluir'): if ($nome == '' || strlen($nome) < 3): $mensagem .= '<li>Favor preencher o Nome.</li>'; endif; if ($cpf == ''): $mensagem .= '<li>Favor preencher o CPF.</li>'; elseif(strlen($cpf) < 11): $mensagem .= '<li>Formato do CPF inválido.</li>'; endif; if ($email == ''): $mensagem .= '<li>Favor preencher o E-mail.</li>'; elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)): $mensagem .= '<li>Formato do E-mail inválido.</li>'; endif; if ($data_nascimento == ''): $mensagem .= '<li>Favor preencher a Data de Nascimento.</li>'; else: $data = explode('/', $data_nascimento); if (!checkdate($data[1], $data[], $data[2])): $mensagem .= '<li>Formato da Data de Nascimento inválido.</li>'; endif; endif; if ($telefone == ''): $mensagem .= '<li>Favor preencher o Telefone.</li>'; elseif(strlen($telefone) < 10): $mensagem .= '<li>Formato do Telefone inválido.</li>'; endif; if ($celular == ''): $mensagem .= '<li>Favor preencher o Celular.</li>'; elseif(strlen($celular) < 11): $mensagem .= '<li>Formato do Celular inválido.</li>'; endif; if ($status == ''): $mensagem .= '<li>Favor preencher o Status.</li>'; endif; if ($mensagem != ''): $mensagem = '<ul>' . $mensagem . '</ul>'; echo "<div class='alert alert-danger' role='alert'>".$mensagem."</div> "; exit; endif; // Constrói a data no formato ANSI yyyy/mm/dd $data_temp = explode('/', $data_nascimento); $data_ansi = $data_temp[2] . '/' . $data_temp[1] . '/' . $data_temp[]; endif; // Verifica se foi solicitada a inclusão de dados if ($acao == 'incluir'): $nome_foto = 'padrao.jpg'; if(isset($_FILES['foto']) && $_FILES['foto']['size'] > ): $extensoes_aceitas = array('bmp' ,'png', 'svg', 'jpeg', 'jpg'); $extensao = strtolower(end(explode('.', $_FILES['foto']['name']))); // Validamos se a extensão do arquivo é aceita if (array_search($extensao, $extensoes_aceitas) === false): echo "<h1>Extensão Inválida!</h1>"; exit; endif; // Verifica se o upload foi enviado via POST if(is_uploaded_file($_FILES['foto']['tmp_name'])): // Verifica se o diretório de destino existe, senão existir cria o diretório if(!file_exists("fotos")): mkdir("fotos"); endif; // Monta o caminho de destino com o nome do arquivo $nome_foto = date('dmY') . '_' . $_FILES['foto']['name']; // Essa função move_uploaded_file() copia e verifica se o arquivo enviado foi copiado com sucesso para o destino if (!move_uploaded_file($_FILES['foto']['tmp_name'], 'fotos/'.$nome_foto)): echo "Houve um erro ao gravar arquivo na pasta de destino!"; endif; endif; endif; $sql = 'INSERT INTO tab_clientes (nome, email, cpf, data_nascimento, telefone, celular, status, foto) VALUES(:nome, :email, :cpf, :data_nascimento, :telefone, :celular, :status, :foto)'; $stm = $conexao->prepare($sql); $stm->bindValue(':nome', $nome); $stm->bindValue(':email', $email); $stm->bindValue(':cpf', $cpf); $stm->bindValue(':data_nascimento', $data_ansi); $stm->bindValue(':telefone', $telefone); $stm->bindValue(':celular', $celular); $stm->bindValue(':status', $status); $stm->bindValue(':foto', $nome_foto); $retorno = $stm->execute(); if ($retorno): echo "<div class='alert alert-success' role='alert'>Registro inserido com sucesso, aguarde você está sendo redirecionado ...</div> "; else: echo "<div class='alert alert-danger' role='alert'>Erro ao inserir registro!</div> "; endif; echo "<meta http-equiv=refresh content='3;URL=index.php'>"; endif; // Verifica se foi solicitada a edição de dados if ($acao == 'editar'): if(isset($_FILES['foto']) && $_FILES['foto']['size'] > ): // Verifica se a foto é diferente da padrão, se verdadeiro exclui a foto antiga da pasta if ($foto_atual <> 'padrao.jpg'): unlink("fotos/" . $foto_atual); endif; $extensoes_aceitas = array('bmp' ,'png', 'svg', 'jpeg', 'jpg'); $extensao = strtolower(end(explode('.', $_FILES['foto']['name']))); // Validamos se a extensão do arquivo é aceita if (array_search($extensao, $extensoes_aceitas) === false): echo "<h1>Extensão Inválida!</h1>"; exit; endif; // Verifica se o upload foi enviado via POST if(is_uploaded_file($_FILES['foto']['tmp_name'])): // Verifica se o diretório de destino existe, senão existir cria o diretório if(!file_exists("fotos")): mkdir("fotos"); endif; // Monta o caminho de destino com o nome do arquivo $nome_foto = date('dmY') . '_' . $_FILES['foto']['name']; // Essa função move_uploaded_file() copia e verifica se o arquivo enviado foi copiado com sucesso para o destino if (!move_uploaded_file($_FILES['foto']['tmp_name'], 'fotos/'.$nome_foto)): echo "Houve um erro ao gravar arquivo na pasta de destino!"; endif; endif; else: $nome_foto = $foto_atual; endif; $sql = 'UPDATE tab_clientes SET nome=:nome, email=:email, cpf=:cpf, data_nascimento=:data_nascimento, telefone=:telefone, celular=:celular, status=:status, foto=:foto '; $sql .= 'WHERE id = :id'; $stm = $conexao->prepare($sql); $stm->bindValue(':nome', $nome); $stm->bindValue(':email', $email); $stm->bindValue(':cpf', $cpf); $stm->bindValue(':data_nascimento', $data_ansi); $stm->bindValue(':telefone', $telefone); $stm->bindValue(':celular', $celular); $stm->bindValue(':status', $status); $stm->bindValue(':foto', $nome_foto); $stm->bindValue(':id', $id); $retorno = $stm->execute(); if ($retorno): echo "<div class='alert alert-success' role='alert'>Registro editado com sucesso, aguarde você está sendo redirecionado ...</div> "; else: echo "<div class='alert alert-danger' role='alert'>Erro ao editar registro!</div> "; endif; echo "<meta http-equiv=refresh content='3;URL=index.php'>"; endif; // Verifica se foi solicitada a exclusão dos dados if ($acao == 'excluir'): // Captura o nome da foto para excluir da pasta $sql = "SELECT foto FROM tab_clientes WHERE id = :id AND foto <> 'padrao.jpg'"; $stm = $conexao->prepare($sql); $stm->bindValue(':id', $id); $stm->execute(); $cliente = $stm->fetch(PDO::FETCH_OBJ); if (!empty($cliente) && file_exists('fotos/'.$cliente->foto)): unlink("fotos/" . $cliente->foto); endif; // Exclui o registro do banco de dados $sql = 'DELETE FROM tab_clientes WHERE id = :id'; $stm = $conexao->prepare($sql); $stm->bindValue(':id', $id); $retorno = $stm->execute(); if ($retorno): echo "<div class='alert alert-success' role='alert'>Registro excluído com sucesso, aguarde você está sendo redirecionado ...</div> "; else: echo "<div class='alert alert-danger' role='alert'>Erro ao excluir registro!</div> "; endif; echo "<meta http-equiv=refresh content='3;URL=index.php'>"; endif; ?> </div> </body> </html> |
Resultado Final
Ao clicar no link “Excluir” do cliente Linus Torvalds é exibida a mensagem de confirmação:
Depois de excluído o cliente é exibida a mensagem de sucesso:
Após 3 segundos é feito o redirecionamento para página “index.php“:
Bom pessoal nesse post expliquei como montar a exclusão de registros, assim finalizo a série de posts sobre sistema de cadastro com PHP + PDO no MySQL. No decorrer desses 4 posts apresentei as facilidades de se construir um layout com bootstrap, um pouco do JavaScript puro sem uso do jQuery ou plugins e também as funcionalidades da extensão PDO com o SGBD MySQL.
Espero que esses exemplos possam ajudar o leitor de alguma forma, direcionando para construção de sistemas mais complexos e eficientes.
Link para Download do projeto final com INCLUSÃO, EDIÇÃO, EXCLUSÃO E CONSULTA. (8161 downloads)
Até a próxima …