jueves, 9 de abril de 2009

Manual de PHP 74. MySQL: Añadir datos mediante formularios

Continuando con los manuales de PHP, en esta entrada describo cómo añadir datos a tu base de datos desde un formulario HTML.





Creación del formulario

El caso más frecuente -casi el único- es que los registros de una tabla se añadan utilizando un formulario y enviando desde él los datos a un script PHP que ejecute la opción de añadir. Si no recuerdas el funcionamiento de este método, pulsa aquí



En el ejemplo hemos desarrollado un formulario para añadir registros a la tabla demo4 con las siguientes peculiaridades:

  • Para los campos DNI, nombre y apellidos hemos utilizado input tipo texto y hemos recogido mediante la opción name cada uno de los campos en una variable independiente.
  • Para los campos Fecha de nacimiento y hora de nacimiento hemos utilizado tres opciones select en cada una de ellas.
    La finalidad de estas opciones no es otra que impedir la introducción de fechas no válidas (en realidad no lo impedimos totalmente ya que, tal como está confeccionado, podría introducirse 31 de febrero, o 31 de abril). Ese aspecto es mejorable, pero para hacerlo –desde el propio formulario– tendríamos de recurrir a un lenguaje del lado del cliente (JavaScrpt por ejemplo).
  • Los valores de esos tres campos (tanto en fecha como en hora) los recogemos en variables que son elementos de dos array escalares.
  • El campo sexo la recogemos en input tipo radio y les asignamos valores M ó F que coinciden con los valores del campo ENUM de la tabla.
  • Con el campo Fumador -opción Fumador/No fumador - hacemos exactamente lo mismo, pero asignándoles valores 1 o 0 ya que el formulario no permite la opción NULL ó cadena vacia.
    En el script posterior será cuando modifiquemos los valores de esas variables.
  • Para el campo Idiomas utilizamos una opción select de tipo múltiple y para los values un pequeño truco que describimos aquí más adelante.
Pues bien, aquí tienes, código fuente del formulario que hemos diseñado:


<html>

<head>

<title>Formulario para añadir datos a la tabla demo4</title>

</head>

<body>

<center><h2>Tabla «demo4»<br>Formulario de altas<h2></center>



<!-- creamos un formulario en el que recogeremos los valores

a añadir a la base de datos demo4

utilizaremos los mismos nombres de variables que en aquel

- por razones de comodidad- anteponiendoles p_ //-->



<form name="altas" method="POST" action="ejemplo173.php">

<table bgcolor="#E9FFFF" align=center border=2>



<td align="right">Escribe tu D.N.I.: </td>

<td align="left"> <input type="text" name="p_v1" value="" size=8></td><tr>

<td align="right">Nombre....: </td>

<td align="left"> <input type="text" name="p_v2" value="" size=20></td><tr>

<td align="right">Primer apellido....: </td>

<td align="left"> <input type="text" name="p_v3" value="" size=15></td><tr>

<td align="right">Segundo apellido...: </td>

<td align="left"> <input type="text" name="p_v4" value="" size=15></td><tr>

<td align="right">Fecha de nacimiento: </td>



<!-- para evitar fechas de nacimiento incorrectas

utilizamos la opción select para asignarles valores

y recogemos e un array de indices 0, 1 y 2

los valores respectivos de año, mes y día

con el ánimo de mantener la misma secuencia

con la que MySQL registrará estos datos //-->





<td align="left"> <select name="p_v5[2]">

<!-- insertamos un script PHP que nos genere autmaticamente las options con valores entre

1 y 31 (se trata del campo dias //-->



<? for ($i=1;$i<32;$i++){

echo "<option>$i</option>";

}

?>

</select> de



<!-- repetimos un bucle como el anterior las options de mes

esta vez entre 1 y 12 (se trata del campo dias //-->



<select name="p_v5[1]">

<? for ($i=1;$i<13;$i++){

echo "<option>$i</option>";

}

?>

</select> de



<!-- ahora el bucle para años, tratándose de fechas de nacimiento

pongámoslas en el intervalo 1935 - 2003 //-->



<select name="p_v5[0]">

<? for ($i=1935;$i<2004;$i++){

echo "<option>$i</option>";

}

?>



<!-- el sexo lo recogemos mediante una una opcion

tipo radio y le asignamos cheked al valor M

para obligar a que tenga el mismo valor

El unico detalle relevante es que el name ha de ser el mismo

en ambos botones de opcion //-->



</select></td><tr>

<td align="right">Sexo...:</td>

<td align="left"> <input type="radio" name="p_v6" value="M" checked > Masculino <input type="radio" name="p_v6" value="F" > Femenino </td><tr>

<td align="right">Hora de nacimiento: </td>





<!-- para insertar la hora de nacimiento utilizamos la misma

estrategia que para la fecha de nacimiento

utilizando un array como variable y asignando

los indices 0, 1 y 2 para

horas, minutos y segundos respectivamente //-->



<td align="left"> <select name="p_v7[0]">

<? for ($i=0;$i<24;$i++){

echo "<option>$i</option>";

}

?>



</select> h

<select name="p_v7[1]">

<? for ($i=0;$i<60;$i++){

echo "<option>$i</option>";

}

?>

</select> m

<select name="p_v7[2]">

<? for ($i=0;$i<60;$i++){

echo "<option>$i</option>";

}

?>

</select> s</td><tr>



<!-- volvemos a utilizar la opción radio para asignar valor 1 al caso de fumador

valor 0 en el caso de no fumador y recogemos el resultado

en la variable p_v8 //-->



<td align="right">Fumador:</td>

<td align="left"> <input type="radio" name="p_v8" value="1" checked > Si <input type="radio" name="p_v8" value="0" > No </td><tr>



<!-- la opción idiomas la activamos mediante un SELECT MULTIPLE

que permite visualizar las OPCIONES DE IDIOMA

POR EL MISMO ORDEN EN QUE FUERON DEFINIDAS

EN LA OPCION SET DE LA BASE DE DATOS

A cada una de las opciones les asignamos como valor

una POTENCIA DE DOS empezando por

2 elevado 0, 2 elevado 1, 2 elevado 2, etc.

la finalidad de esta estrategia es permitir

que en el formulario de ALTAS

se puedan sumar estos valores y que esa suma

se el valor decimal equivalente al valor binario

de las opciones seleccionadas

El array p_v9 recogerá con indices correlativos

a partir de 0, unicamente los valores de

AQUELLAS OPCIONES QUE HAN SIDO SELECCIONADAS //-->







<td align="right">Habla:<br>

(<i>Si habla varios seleccionarlos<br>

pulsando con el mouse encima de <br>

cada uno de ellos con la tecla<br>

<b>Ctrl</b> presionada</i>)</td>

<td align="left"> <SELECT MULTIPLE name=p_v9[] SIZE=6>

<option value=1>Castellano</option>

<option value=2>Francés</option>

<option value=4>Inglés</option>

<option value=8>Alemán</option>

<option value=16>Búlgaro</option>

<option value=32>Chino</option>

</select>

</td><tr>



<!--colocamos los botones de enviar y borrar //-->





<td align=center><input type=submit value="Enviar"></td>

<td align=center><input type=reset value="Borrar"></td>

</form>

</table>

</body>

</html>




Añadir nuevo registro con datos del formulario

Como recordarás, cuando se envía el contenido de un formulario mediante el method=POST y se indica como action un fichero PHP los valores enviados son recogidos en este último fichero en variables de PHP que tienen como nombre $_POST['var'] –o $HTTP_POST_VARS['var']– donde cada una de los índices asociativos de los array (var) coinciden con los name de los diferentes campos del formulario.

A partir de ahí, bastaría con depurar los valores recibos, recoger en variables los valores depurados e incluirlos en la sentencia MySQL INSERT -la hemos visto en la página anterior- para añadirlos a la tabla correspondiente. Aquí tienes –comentado– el script:


<?

# recogemos en una variable el nombre de BASE DE DATOS

$base="ejemplos";



# recogemos en una variable el nombre de la TABLA

$tabla="demo4";



# recoger y adaptar las variables pasadas desde el formulario

# ni el DNI ni los nombres y apellidos necesitan ninguna modificacion

# por eso los pasamos a la variable intermedia directamente

/* estas variables intermedias podrían evitarse. El hecho de usarlas

obedece unicamente a un intento de mayor claridad en la interpretación

de este codigo fuente */

$v1=$_POST['p_v1'];

$v2=$_POST['p_v2'];

$v3=$_POST['p_v3'];

$v4=$_POST['p_v4'];



/* Leemos el array pv__5 y lo recogemos

en un array escalar de indices autonumericos

(nacimiento) teniendo en cuenta que el orde sería

dia, mes y año, ya que así lo hemos insertado

en los indices del formulario */

foreach ($_POST['p_v5'] as $valor){

$nacimiento[]=$valor;

}



/* creamos la variable fecha de nacimiento

ENCADENANDO el array anterior

FIJATE QUE LO HACEMOS EN ORDEN INVERSO

PORQUE MySQL REQUIERE FECHAS CON FORMATO

AÑO-MES-DIA (AAAA-MM-DD) */

$v5=$nacimiento[2]."-".$nacimiento[1]."-".$nacimiento[0];



# la variable Sexo la recogemos sin modificaciones

# ya que desde el formulario solo recibimos

# valor M ó valor F

$v6=$_POST['p_v6'];



/* Leemos el array pv__5 y lo recogemos

en un array escalar (hora) de indices autonumericos

teniendo en cuenta que el orde sería

dia, mes y año, ya que así lo hemos insertado

en los indices del formulario */

foreach ($_POST['p_v7'] as $valor){

$hora[]=$valor;

}



/* encadenamos los elementos del array hora en formato válido

MySQL, es decir: hora:minutos:segundos (hh:mm:ss) */

$v7=$hora[0].":".$hora[1].":".$hora[2];



# la variable $p_v8 puede contener valores

# 0 (no fumador) ó 1 (si fumador)

# con este bucle asignamos NULL para el primero de los casos

# o CADENA VACIA para el segundo

# ¡¡Atención......

# fijate como pasamos la cadena vacia

# y fijate que en el INSERT no ponemos la variable $v8 entre comillas

# es la excepción para el tipo de variable CHAR(O)

# LA UNICA QUE NO PASAMOS ENTRECOMILLADA

if ($_POST['p_v8']==0) {

$v8='"\n"';

}else{

$v8='""';

}



# el truco de asignar en el formulario valores 1,2,4,8,16,32 a las opciones de idioma

# nos permite sumarlos aquí para obtener el valor conjunto

# aqui se suman todos los valores de la matriz pasada desde el formulario

foreach($_POST['p_v9'] as $valor) {

$v9+=$valor;

};



# establecemos la conexion con el servidor

$c=mysql_connect("localhost","pepe","pepa");



#asiganamos la conexión a una base de datos determinada

mysql_select_db($base,$c);



# AÑADIMOS EL NUEVO REGISTRO

/* CUIDADO.....

SOLO LAS VARIABLES NUMERICAS VAN SIN COMILLAS AL INSERTAR LOS VALOES

OBSERVA EN VALUES QUE LAS VARIABLES NO NUMERICAS SE INSERTAN

ENTRE COMILLAS..... */

mysql_query("INSERT $tabla (DNI,Nombre,Apellido1,Apellido2, Nacimiento,Sexo,Hora,Fumador,Idiomas) VALUES ('$v1','$v2','$v3','$v4','$v5','$v6','$v7',$v8,'$v9')",$c);



#comprobamos el resultado de la insercion

# el error CERO significa NO ERROR

# el error 1062 significa Clave duplicada

# en otros errores forzamos a que nos ponga el número de error

# y el significado de ese error (aunque sea en ingles)....

if (mysql_errno($c)==0){echo "<h2>Registro AÑADIDO</b></H2>";

}else{

if (mysql_errno($c)==1062){echo "<h2>No ha podido añadirse el registro<br>Ya existe un campo con este DNI</h2>";

}else{

$numerror=mysql_errno($c);

$descrerror=mysql_error($c);

echo "Se ha producido un error nº $numerror que corresponde a: $descrerror <br>";

}

}



# cerramos la conexion

mysql_close();



?>




En realidad, tal como habrás podido ver en el código fuente, la depuración ha sido la siguiente:
  • Hemos creado un valor de fecha y hora en formatos MySQL válidos de la forma que describimos un poco más arriba.
  • Hemos sumado todos los valores numéricos recibidos en el array obtenido del SELECT MULTIPLE y hemos asignado el resultado a la variable depurada que recoge el valor a escribir en el campo Idiomas. La justificación de esa suma la tienes al final de la entrada.
  • La variable Fumador es la que tiene un poquito más de complicación. Veámosla con calma:
    Los valores que recibimos desde formulario son 1 o 0 y hemos de transformarlos en una cadena vacía o en NULL. Hemos insertado un operador condicional (un if... else) para convertir eso valores en: $var="'\N'" (comilla doble, comilla simple, barra invertida, N, comilla simple y comilla doble) ó $var="''" (comillas dobles, dos comillas simples y unas comillas dobles)
  • Asignados los nuevos valores tenemos que recurrir a un pequeño truco. Venimos repitiendo que en la sentencia INSERT los nombres de las variables no numéricas que contienen los values hay que escribirlos dentro de comillas simples, pero en el caso de un campo tipo CHAR(0) hemos de hacer una excepción que sería no poner esas comillas al nombre de la variable. Al hacerlo así, se escribirían como valores –en la sentencia de inserción– uno de estos: ='\N' o =' ' (los valores de la variable) que al contener comillas ya son interpretados por MySQL como una cadena.


Los valores de SELECT MULTIPLE

La opción SELECT MULTIPLE dentro de un form típico de HTML permite elegir ninguno, uno o varios de los elementos de la lista.

Basta con pulsar con el ratón sobre cada uno de los valores elegidos manteniendo pulsada la tecla Ctrl, es decir, puro Windows.

Para recoger los valores de esa opción se define -dentro de la etiqueta SELECT- un name tipo array. Bastaría con escribir:

<SELECT MULTIPLE

name=var[] SIZE=6>


Como ves, var es el nombre de la variable (esta vez sin $ delante, recuerda que no estamos en PHP sino en puro HTML) y va seguido de [] precisamente para indicar que es un array.

Lo de SIZE=6 no es otra cosa que el parámetro que indica cuántos elementos de la lista de opciones queremos que se visualicen simultáneamente en la página.

El truco está en los values de cada option dentro de ese select

Los hemos escrito así:


<option value=1>Castellano

<option value=2>Francés

<option value=4>Inglés

<option value=8>Alemán

<option value=16>Búlgaro

<option value=32>Chino




Fíjate que hemos mantenido exactamente el mismo orden en el que han sido definidos en el campo SET de la tabla.

Y fíjate también en los valores: 1, 2, 4, 8, 16 y 32 que son precisamente las potencias de 2:

20, 21, 22, 23, 24, 25, y 26

Al ir seleccionando valores, van añadiéndose al array. Por ejemplo. Si seleccionamos Francés y Búlgaro el array sería este: var[0]=2, var[1]=16

Si sumamos esos valores (2 + 16) el resultado sería 18, y al convertir a binario este valor, resultará:

010010

que es como decirle a MySQL (mirando la cadena de derecha a izquierda, ¿lo recuerdas?) que incluya los valores segundo (Francés) y quinto (Búlgaro) del SELECT MULTIPLE que corresponden a las posiciones en las que la cadena binaria contiene un uno.





Fuente:



1 comentario:

kidbrush dijo...

la verdas esta genial este manualillo

felicidades e estado revisando manuales y documentos y este esta genial no detallado pero dicen que un buen codigo escrito no necesita documentacion asi que el tuyo esta bien escrito felizidadez