PHP UD3 OP MODIFICAR
Revisión del 06:43 25 oct 2023 de Angelfg (discusión | contribuciones)
Introducción
- Requerimentos previos: Ter creada a base de datos indicada nunha sección anterior e ter gardados os parámetros de conexión nun arquivo separado como foi indicado nunha sección anterior
- NOTA IMPORTANTE: Vimos en seccións anteriores que cando empregmos datos dun formulario, existen unhas técnicas para evitar posibles ataques. Todos os exercicios que veñen a continuación empregan ditas técnicas. Existe un tipo de ataque que non se ten en conta ao non ter chegado á sección de emprego de variables de sesións. En dita sección se explica o que temos que facer. É importante que vos acordedes de aplicar a técnica descrita cando vexades os contidos.
- A modificación se produce cando executamos a orde SQL UPDATE.
- Ao igual que no caso INSERT, se modificamos as claves primarias, farase o action recollido na creación das táboas.
- Normalmente non se debe modificar a clave primaria das táboas e o que modificaremos será algún dos atributos da táboa.
- A orde SQL UPDATE levará como parámetros os novos valores a modificar e enviarase a clave primaria para que poida buscar a fila concreta que vai modificarse.
- Ao igual que no caso da orde INSERT, podemos saber o número de rexistros afectados chamando á función mysqi_affected_rows.
- Neste exercicio dita función debería devolver sempre 1, pero podería aplicarse a outros exemplo no que queremos informar ao usuario de cantos rexistros foron afectados pola opción.
- Nota: Lembrar que nesta solución estamos a utilizar a chamada a multi_query pero se podería utilizar a chamada a query no caso de que o procedemento non devolva resultados (teña un select que queiramos recoller en PHP).
Caso Práctico: Modificación
- Seguindo có noso exemplo imos a rematar a páxina 'Xestionar_Estados_Proc.php' engadindo a funcionalidade para modificar os estados.
- Cando se seleccione esta opción aparecerá unha lista. Deberemos escoller un estado da lista e teremos unha caixa de texto para darlle o novo valor ao elemento seleccionado.
- Ao premer o botón 'Modificar' modificarase o estado do elemento seleccionado.
- Comprobaremos antes de facer a modificación, que estea seleccionado un elemento da lista.
Nota: Neste curso non entramos en temas de 'presentación' e 'javascript/jquery'. Por iso a 'presentación' de cara a un usuario final non é a adecuada.
- Neste caso poderíamos implementar, con 'javascript', que o usuario teña que seleccionar un elemento da lista antes de premer o botón 'Modificar'.
- Tamén poderíamos implementar con jquery/javascript unha lista 'editable'.
Posible solución Caso Práctico: Modificación
Procedemento almacenado de Mysql MODIFICAR_ESTADO
DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `MODIFICAR_ESTADO`(_id_estado int,_descripcion varchar(100)) BEGIN UPDATE ESTADOS SET descripcion=_descripcion WHERE id_estado = _id_estado; END
Arquivo: bd.inc.php
1 define ('PROCEDEMENTO_MODIFICAR_ESTADO',"BORRAR_ESTADO(%d,'%s')");
Arquivo: Xestionar_Estados_Proc.php
1 <?php 2 3 require ('/var/www/confBD/bd.inc.php'); 4 //error_reporting(0); 5 6 $conex = new mysqli(SERVIDOR,USUARIO,PASSWORD,BD); 7 $conex->set_charset('utf8'); 8 9 if ($conex->connect_error){ 10 die('Erro de Conexión (' . mysqli_connect_errno() . ') ' . mysqli_connect_error()); 11 } 12 $erro=""; // Variable que a usaremos para amosar os posibles erros que poidan darse 13 ?> 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 17 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 18 <html xmlns="http://www.w3.org/1999/xhtml" lang="es" xml:lang="es"> 19 <head> 20 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 21 <title>Xestionar táboa Estados BD</title> 22 </head> 23 24 <body> 25 <!-- Esta parte poderíase facer con javascript --> 26 <form action="<?php echo htmlentities($_SERVER['PHP_SELF']) ?>" method='post'> 27 <h2>Escolle a operación a facer sobre a táboa ESTADOS</h2> 28 <input <?php echo (isset($_POST['rbtnOperacion']) && $_POST['rbtnOperacion']=='ALTA') ? "checked='checked'" : ""; ?> 29 onclick='javascript:this.form-submit()' type='radio' name="rbtnOperacion" value='ALTA'>ALTA</input> 30 <input <?php echo (isset($_POST['rbtnOperacion']) && $_POST['rbtnOperacion']=='BAIXA') ? "checked='checked'" : ""; ?> 31 onclick='javascript:this.form-submit()' type='radio' name="rbtnOperacion" value='BAIXA'>BAIXA</input> 32 <input <?php echo (isset($_POST['rbtnOperacion']) && $_POST['rbtnOperacion']=='MODIFICACION') ? "checked='checked'" : ""; ?> 33 onclick='javascript:this.form-submit()' type='radio' name="rbtnOperacion" value='MODIFICACION'>MODIFICACIÓN</input> 34 <?php 35 36 // Operación BAIXA => TEN QUE IR ANTES XA QUE DESPOIS CARGAMOS A LISTA COS ESTADOS!!! 37 if (!empty($_POST['btnOperacion']) && $_POST['btnOperacion']=='BAIXA'){ 38 $id_estado = $_POST['lstEstados']; 39 if (!filter_var($id_estado,FILTER_VALIDATE_INT)){ 40 $error='<h4>O estado indicado non é válido...</h4>'; 41 } 42 else { 43 $proc = sprintf(PROCEDEMENTO_BORRAR_ESTADO,$conex->mysql_real_escape($id_estado)); 44 $proc = sprintf("CALL %s",$proc); 45 if ($conex->multi_query($proc)){ 46 printf("<h4>Num. rexistros borrados:%d</h4>", $conex->affected_rows); 47 echo "<script>alert('Rexistro dado de baixa correctamente');</script>"; 48 while($conex->next_result() && $conex->store_result()); 49 } 50 else{ 51 echo "<h5>Falló CALL: (" . $conex->errno . ") " . $conex->error . "</h5>"; 52 if ($conex->errno==1451){ // Clave foránea relacionada 53 echo "<script>alert('O rexistro non se pode dar de baixa. Está sendo utilizado por outras táboas.');</script>"; 54 } 55 } 56 } 57 } // Fin da operación de BAIXA 58 59 // OPERACION DE MODIFICAR 60 if (!empty($_POST['btnOperacion']) && $_POST['btnOperacion']=='MODIFICAR'){ 61 if (empty($_POST['lstEstados'])){ 62 $erro='É necesario seleccionar un estado da lista...'; 63 } 64 else { 65 $id_estado = $_POST['lstEstados']; 66 if (!filter_var($id_estado,FILTER_VALIDATE_INT)){ 67 $erro='<h4>O estado indicado non é válido...</h4>'; 68 } 69 elseif (strlen($_POST['txtEstado'])>100){ 70 $erro = ">A lonxitude da cadea non pode ter máis de 100 caracteres..."; 71 } 72 else { 73 // Eliminamos caracteres non permitidos 74 $novoEstado = filter_var($_POST['txtEstado'],FILTER_SANITIZE_STRING); 75 // Escapamos as comillas simples e dobres 76 $novoEstado = $conex->real_escape_string($novoEstado); 77 $proc=sprintf(PROCEDEMENTO_MODIFICAR_ESTADO,$conex->mysql_real_escape($id_estado),$novoEstado); 78 $proc = sprintf("CALL %s",$proc); 79 if ($conex->multi_query($proc)){ 80 printf("<h4>Num. rexistros modificados:%d</h4>", $conex->affected_rows); 81 while($conex->next_result() && $conex->store_result()); 82 } 83 else{ 84 echo "<h5>Falló CALL: (" . $conex->errno . ") " . $conex->error . "</h5>"; 85 } 86 87 } 88 } 89 } // Fin da operación de MODIFICAR 90 91 92 93 // CARGAMOS AS DIFERENTES OPCIONS DE FORMULARIO EN BASE A OPERACION ESCOLLIDA DOS RADIOBUTTON: ALTA-BAIXA-MODIFICACION 94 if (!empty($_POST['rbtnOperacion'])){ // Premimos unha opción => Xeramos o formulario 95 switch ($_POST['rbtnOperacion']){ 96 case 'ALTA': 97 printf("<div>Nome do novo estado:"); 98 printf("<input name='txtEstado' type='text' size='50' maxlength='100' /></div>"); 99 printf("<div><input name='btnOperacion' type='submit' value='ALTA' />"); 100 printf("<input type='reset' value='BORRAR' /></div>"); 101 break; 102 case 'BAIXA': 103 printf("<div>Lista de estados:"); 104 $proc = sprintf("CALL %s",PROCEDEMENTO_CONSULTAR_ESTADOS); 105 printf("<select name='lstEstados'>"); 106 if ($conex->multi_query($proc)){ 107 $result = $conex->store_result(); 108 if ($result && ($result->num_rows>0)){ 109 while($fila=$result->fetch_assoc()){ 110 printf("<option value='%d'>%s</option>",$fila['id_estado'],$fila['descripcion']); 111 } 112 $result->free(); 113 } 114 while($conex->next_result() && $conex->store_result()); 115 } 116 printf("</select>"); 117 printf("</div>"); 118 printf("<div><input name='btnOperacion' type='submit' value='BAIXA' />"); 119 break; 120 case 'MODIFICACION': 121 printf("<div>"); 122 $proc = sprintf("CALL %s",PROCEDEMENTO_CONSULTAR_ESTADOS); 123 printf("<select name='lstEstados' size='10'>"); 124 if ($conex->multi_query($proc)){ 125 $result = $conex->store_result(); 126 if ($result && ($result->num_rows>0)){ 127 while($fila=$result->fetch_assoc()){ 128 printf("<option value='%d'>%s</option>",$fila['id_estado'],$fila['descripcion']); 129 } 130 $result->free(); 131 } 132 while($conex->next_result() && $conex->store_result()); 133 } 134 printf("</select>"); 135 printf("Novo valor: <input name='txtEstado' type='text' size='50' maxlength='100' />"); 136 printf("</div>"); 137 printf("<div><input name='btnOperacion' type='submit' value='MODIFICAR' />"); 138 break; 139 140 } 141 } 142 ?> 143 </form> 144 145 <?php 146 // Xestionamos a operacion do segundo formulario => Alta 147 if (!empty($_POST['btnOperacion']) && $_POST['btnOperacion']=='ALTA'){ 148 if (strlen($_POST['txtEstado'])>100){ 149 $erro = ">A lonxitude da cadea non pode ter máis de 100 caracteres..."; 150 } 151 else { 152 // Eliminamos caracteres non permitidos 153 $novoEstado = filter_var($_POST['txtEstado'],FILTER_SANITIZE_STRING); 154 // Escapamos as comillas simples e dobres 155 $novoEstado = $conex->real_escape_string($novoEstado); 156 $proc=sprintf(PROCEDEMENTO_INSERIR_ESTADO,$novoEstado); 157 $proc = sprintf("CALL %s",$proc); 158 if ($conex->multi_query($proc)){ 159 $result = $conex->store_result(); 160 if ($result && ($result->num_rows>0)){ 161 $fila=$result->fetch_assoc(); 162 switch($fila['valor_devolto']){ 163 case -1: 164 $erro = "Ese valor xa está dado de alta na base de datos..."; 165 break; 166 default: 167 printf("<h2>Valor dado de alta correctamente</h2>"); 168 printf("<h3>Nova clave %d</h3>",$fila['valor_devolto']); 169 170 break; 171 } 172 $result->free(); 173 } 174 else{ // Sempre ten que devolver algo como temos implementado o proc. 175 $erro = 'Houbo un erro na chamada á base de datos'; 176 } 177 while($conex->next_result() && $conex->store_result()); 178 } 179 else{ 180 $erro = 'Houbo un erro na chamada á base de datos'; 181 } 182 } 183 184 } // Fin da operacion de ALTA 185 186 187 188 ?> 189 <?php 190 if ($erro!='') { 191 printf("<h3>%s</h3>",$erro); 192 } 193 $conex->close(); // Pechamos a conexión 194 195 ?> 196 197 198 </body> 199 </html>
-- Ángel D. Fernández González -- (2023).