Diferencia entre revisiones de «PHP UD3 OP MODIFICAR»

De MediaWiki
Ir a la navegación Ir a la búsqueda
(Página creada con « * A modificación se produce cando executamos a [http://www.w3schools.com/sql/sql_update.asp orde SQL UPDATE]. * Ao igual que no caso INSERT, se modificamos as claves pr…»)
 
Línea 1: Línea 1:
 +
===Introducción===
 +
 +
 +
 +
* '''<u>Requerimentos previos:</u>''' Ter creada a base de datos indicada [https://wiki.cifprodolfoucha.es/index.php?title=PHP_Operaci%C3%B3ns_BD_Mysql#Creando_as_t.C3.A1boas_en_Mysql nunha sección anterior] e ter gardados os parámetros de conexión nun arquivo separado [https://wiki.cifprodolfoucha.es/index.php?title=PHP_Operaci%C3%B3ns_BD_Mysql#Gardando_os_datos_de_conexi.C3.B3n_nun_lugar_seguro como foi indicado nunha sección anterior]
 +
 +
 +
 +
* '''NOTA IMPORTANTE:''' [https://wiki.cifprodolfoucha.es/index.php?title=PHP_Paso_de_datos_con_formularios#Seguridade_no_uso_dos_formularios 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 á [https://wiki.cifprodolfoucha.es/index.php?title=PHP_Sesi%C3%B3ns#Ataques_CSRF_.28Cross-Site_Request_Forgery.29 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.
 +
 +
 +
 +
<br />
 +
  
  

Revisión del 06:43 25 oct 2023

Introducción


  • 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.




  • 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.
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&oacute;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&aacute;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&Oacute;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 &eacute; v&aacute;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 &eacute; v&aacute;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&aacute; 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).