Generar SQL desde Arrays de inputs HTML5

¡Muy buenas! Este segundo tutorial del año se centrará en resolver una duda general: cómo obtener [en PHP] los datos de un formulario con inputs que sean arrays e insertar esos datos con SQL (por ejemplo, a MySQL).

Un ejemplo de los input array es este:

<input type="text" name="nombre[]">

Como se puede apreciar, el nombre del campo es nombre[], donde los corchetes hacen que el input con el mismo nombre sepa “auto-identificar” que es un array, y poder tener así varios inputs con el mismo nombre. Esto se utiliza generalmente cuando son necesarios varios inputs para procesar diferentes datos.

¿Cómo pasar cada dato a PHP?


Como siempre digo, seguiré desarrollando en local, utilizando XAMPP (Apache y MySQL con PHPMyAdmin) en Windows.

1 de 4: MySQL

Lo primero que debemos hacer es estructurar nuestra base de datos.
Continúo trabajando sobre una base de datos llamada mmv con cotejamiento utf8_spanish_ci. Dentro tengo una tabla llamada mmv006 que tiene cuatro columnas. El motor de almacenamiento es InnoDB.

  1. id -> INT(5) -> A_I -> primaria
  2. nombre -> varchar(60) -> utf8_spanish_ci
  3. apellido -> varchar(60) -> utf8_spanish_ci
  4. edad -> varchar(2) -> utf8_spanish_ci

2 de 4: HTML, jQuery y AJAX

Para empezar con el formulario, debemos crear un archivo HTML (o PHP) con la estructura de HTML5 estándar. Para este ejemplo, este será el index.php.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Formulario con input arrays</title>
</head>

<body>
</body>
</html>

Ahora vamos a agregar la librería de jQuery en el head del HTML para poder usar la función AJAX. Yo utilizaré la versión 1.9.1 minificada que tengo descargada.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="js/jquery-1.9.1.min.js"></script>
<title>Formulario con input arrays</title>
</head>

<body>
</body>
</html>

Es hora de empezar a estructurar el cuerpo del archivo. Lo primero es crear un contenedor (div #mensaje) donde estarán las respuestas del servidor respecto a las acciones de los usuarios en el formulario. Las respuestas las recibiremos después a través de AJAX.

Después, crearemos el formulario, el cual tendrá método POST, con id add, el action vacío y que acepte UTF-8. En ese ejemplo, crearé tres campos diferentes: nombre, apellido y edad.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="js/jquery-1.9.1.min.js"></script>
<title>Formulario con input arrays</title>
</head>

<body>

<div id="mensaje" style="border:1px solid #CCC; padding:10px;"></div>

<form method="POST" id="add" action="" accept-charset="utf-8">
    <label for="nombre"><p>Nombre</p></label>
    <input type="text" name="nombre[]" autocomplete="off" placeholder="1" maxlength="60" required>
    <input type="text" name="nombre[]" autocomplete="off" placeholder="2" maxlength="60" required>
    <input type="text" name="nombre[]" autocomplete="off" placeholder="3" maxlength="60" required>

    <label for="apellido"><p>Apellido</p></label>
    <input type="text" name="apellido[]" autocomplete="off" placeholder="1"  maxlength="60" required>
    <input type="text" name="apellido[]" autocomplete="off" placeholder="2" maxlength="60" required>
    <input type="text" name="apellido[]" autocomplete="off" placeholder="3" maxlength="60" required>

    <label for="edad"><p>Edad</p></label>
    <input type="number" name="edad[]" autocomplete="off" placeholder="1" maxlength="2" required>
    <input type="number" name="edad[]" autocomplete="off" placeholder="2" maxlength="2" required>
    <input type="number" name="edad[]" autocomplete="off" placeholder="3" maxlength="2" required>

    <br><br>
    <input type="submit" name="add" value="Añadir persona">
</form>

</body>
</html>

A continuación añadiremos, justo antes del fin de la etiqueta </body>, el código de AJAX que enviará la información al archivo PHP que procesará los datos y hará el INSERT en la base de datos.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="js/jquery-1.9.1.min.js"></script>
<title>Formulario con input arrays</title>
</head>

<body>

<div id="mensaje" style="border:1px solid #CCC; padding:10px;"></div>

<form method="POST" id="add" action="" accept-charset="utf-8">
    <label for="nombre"><p>Nombre</p></label>
    <input type="text" name="nombre[]" autocomplete="off" placeholder="1" maxlength="60" required>
    <input type="text" name="nombre[]" autocomplete="off" placeholder="2" maxlength="60" required>
    <input type="text" name="nombre[]" autocomplete="off" placeholder="3" maxlength="60" required>

    <label for="apellido"><p>Apellido</p></label>
    <input type="text" name="apellido[]" autocomplete="off" placeholder="1"  maxlength="60" required>
    <input type="text" name="apellido[]" autocomplete="off" placeholder="2" maxlength="60" required>
    <input type="text" name="apellido[]" autocomplete="off" placeholder="3" maxlength="60" required>

    <label for="edad"><p>Edad</p></label>
    <input type="number" name="edad[]" autocomplete="off" placeholder="1" maxlength="2" required>
    <input type="number" name="edad[]" autocomplete="off" placeholder="2" maxlength="2" required>
    <input type="number" name="edad[]" autocomplete="off" placeholder="3" maxlength="2" required>

    <br><br>
    <input type="submit" name="add" value="Añadir persona">
</form>

<script>
//Guardamos el controlador del div con ID mensaje en una variable
var mensaje = $("#mensaje");
//Ocultamos el contenedor
mensaje.hide();

//Cuando el formulario con ID add se envíe...
$("#add").on("submit", function(e){
	//Evitamos que se envíe por defecto
	e.preventDefault();
	//Creamos un FormData con los datos del mismo formulario
	var formData = new FormData(document.getElementById("add"));

	//Llamamos a la función AJAX de jQuery
	$.ajax({
		//Definimos la URL del archivo al cual vamos a enviar los datos
		url: "recursos/add.php",
		//Definimos el tipo de método de envío
		type: "POST",
		//Definimos el tipo de datos que vamos a enviar y recibir
		dataType: "HTML",
		//Definimos la información que vamos a enviar
		data: formData,
		//Deshabilitamos el caché
		cache: false,
		//No especificamos el contentType
		contentType: false,
		//No permitimos que los datos pasen como un objeto
		processData: false
	}).done(function(echo){
		//Cuando recibamos respuesta, la mostramos
		mensaje.html(echo);
		mensaje.slideDown(500);
	});
});
</script>

</body>
</html>

Y listo. Deberíamos tener algo como esto:

3 de 4: PHP

Bien, ahora en nuestro archivo add.php vamos a procesar todos los datos.

El archivo debe estar totalmente vacío. Las etiquetas HTML (doctype, html, head, body, etc.) que puedan generar algunos editores de texto (como Dreamweaver) deben ser eliminadas.

Entonces le decimos al documento que vamos a escribir PHP y requerimos nuestro archivo de conexión a la BBDD.

<?php
//Archivo de conexión a la base de datos
require('conexion.php');
?>

Después obtenemos los datos de texto del formulario, realizamos un filtro anti-XSS y comprobamos que ningun input venga vacío:

<?php
//Archivo de conexión a la base de datos
require('conexion.php');

//////////////////

//Obtenemos los datos del formData
$array_nombres = $_POST['nombre'];
$array_apellidos = $_POST['apellido'];
$array_edades = $_POST['edad'];

//Filtro anti-XSS para cada uno de los datos de cada array
$array_nombres = array_map("htmlspecialchars", $array_nombres);
$array_apellidos = array_map("htmlspecialchars", $array_apellidos);
$array_edades = array_map("htmlspecialchars", $array_edades);

//Si falta algún dato, "matamos" el proceso
if (empty($array_nombres) OR empty($array_apellidos) OR empty($array_edades)) {
	die('Uno o más campos están vacíos');
};
?>

A continuación realizaremos las comprobaciones necesarias para cada campo de datos (largo de los caracteres, etcétera). Para esto utilizaremos un bucle foreach, para así poder comprobar los datos uno a uno.

<?php
//Archivo de conexión a la base de datos
require('conexion.php');

//////////////////

//Obtenemos los datos del formData
$array_nombres = $_POST['nombre'];
$array_apellidos = $_POST['apellido'];
$array_edades = $_POST['edad'];

//Filtro anti-XSS para cada uno de los datos de cada array
$array_nombres = array_map("htmlspecialchars", $array_nombres);
$array_apellidos = array_map("htmlspecialchars", $array_apellidos);
$array_edades = array_map("htmlspecialchars", $array_edades);

//Si falta algún dato, "matamos" el proceso
if (empty($array_nombres) OR empty($array_apellidos) OR empty($array_edades)) {
	die('Uno o más campos están vacíos');
};

//////////////////

//Hacemos las comprobaciones correspondientes de cada dato obtenido
foreach ($array_nombres as $identificador => $nombre) {
	if (strlen($nombre) > "60") {
		die('El nombre no puede superar los 60 caracteres');
	};
	if (empty($nombre)) {
        	die('Uno o más campos están vacíos');
	};
};

foreach ($array_apellidos as $identificador => $apellido) {
	if (strlen($apellido) > "60") {
		die('El apellido no puede superar los 60 caracteres');
	};
    	if (empty($apellido)) {
        	die('Uno o más campos están vacíos');
	};
};

foreach ($array_edades as $identificador => $edad) {
	if (strlen($edad) > "2") {
		die('La edad no puede superar los 2 caracteres');
	};
	if(!is_numeric($edad)) {
        	die('La edad debe ser numérica');
    	};
    	if (empty($edad)) {
        	die('Uno o más campos están vacíos');
	};
};
?>

Una vez que se haya comprobado que todo está correcto, procedemos a generar la consulta.

Para esto, primero crearemos un array vacío. Acto seguido, creamos un bucle foreach, donde obtendremos cada clave y nombre (key=>value) de $array_nombres, para poder contar la cantidad de claves que hay y asociarlos a su equivalente en los otros arrays (en este caso, $array_apellidos y $array_edades). Y una vez hecho esto, realizamos la consulta y mostramos la respuesta de éxito (en mi caso, además vacío el formulario).

<?php
//Archivo de conexión a la base de datos
require('conexion.php');

//////////////////

//Obtenemos los datos del formData
$array_nombres = $_POST['nombre'];
$array_apellidos = $_POST['apellido'];
$array_edades = $_POST['edad'];

//Filtro anti-XSS para cada uno de los datos de cada array
$array_nombres = array_map("htmlspecialchars", $array_nombres);
$array_apellidos = array_map("htmlspecialchars", $array_apellidos);
$array_edades = array_map("htmlspecialchars", $array_edades);

//Si falta algún dato, "matamos" el proceso
if (empty($array_nombres) OR empty($array_apellidos) OR empty($array_edades)) {
	die('Uno o más campos están vacíos');
};

//////////////////

//Hacemos las comprobaciones correspondientes de cada dato obtenido
foreach ($array_nombres as $identificador => $nombre) {
	if (strlen($nombre) > "60") {
		die('El nombre no puede superar los 60 caracteres');
	};
	if (empty($nombre)) {
        	die('Uno o más campos están vacíos');
	};
};

foreach ($array_apellidos as $identificador => $apellido) {
	if (strlen($apellido) > "60") {
		die('El apellido no puede superar los 60 caracteres');
	};
    	if (empty($apellido)) {
        	die('Uno o más campos están vacíos');
	};
};

foreach ($array_edades as $identificador => $edad) {
	if (strlen($edad) > "2") {
		die('La edad no puede superar los 2 caracteres');
	};
	if(!is_numeric($edad)) {
        	die('La edad debe ser numérica');
    	};
    	if (empty($edad)) {
        	die('Uno o más campos están vacíos');
	};
};

//////////////////

//Si todo está correcto, procedemos a generar la consulta

//Generamos un array vacío
$sql_array = array();

//Obtenemos cada clave y su valor para poder contar la cantidad de datos e ingresarlos acorde a cada clave
foreach ($array_nombres as $clave=>$nombre) {
	$apellido = $array_apellidos[$clave];
	$edad = $array_edades[$clave];
	$datoUnico[] = '("'.$nombre.'", "'.$apellido.'", "'.$edad.'")'; 
	$consulta = "INSERT INTO `mmv006` (`nombre`, `apellido`, `edad`) VALUES " . implode(', ', $datoUnico);
}

//Realizamos la consulta y damos una respuesta
if(mysqli_query($conexion, $consulta)) {
die('Persona(s) ingresada(s)
<script>$("#add")[0].reset();</script>');
};
?>

Y listo. Ya finalizamos el procesado de cada dato y los ingresamos en la base de datos.

4 de 4: Ejemplos

Una vez hecho todo lo anterior, podemos observar los resultados finales. Yo no lo he aplicado ningún estilo, pero se puede hacer sin problemas.

Nombres generados con uinames.com

Nombres generados con uinames.com

Datos guardados en la BBDD

Datos guardados en la BBDD

Conclusión:

Confío en que haya quedado claro el proceso, especialmente el bucle foreach que obtiene cada dato según la clave del array de nombres.

Espero que el tutorial haya sido de utilidad. Nos leemos, ¡saludos!

4 comments

  1. Geraldine · abril 22

    Disculpa, porque al momento de que ingreso mis datos me sale array_map(): Argument #2 should be an array in C:\xampp\htdocs\add.php on line 11

    Me gusta

    • Rocanrol · abril 23

      Hola, Geraldine.

      Es posible que haya un error en el HTML, ¿estás usando como nombre del input algo como “nombre[]”? Es importante que use los dos corchetes, porque estoy declara que es un array.

      Me gusta

  2. uchiha · mayo 12

    Que buen tutorial amigo. tengo una duda. yo estoy haciendo algo parecido, pero entonces supongamos que las 3 personas que hemos añadido, formen parte de un equipo que necesito identificar mediante una clave que sea la misma para ellos 3 pero para no repetir los mismos campos, solo hacer un input, ¿puedo mandar un campo no array dentro del mismo formulario con ese input para los 3? y como podría hacerlo ? Gracias.!

    Me gusta

    • Rocanrol · mayo 12

      Hola.

      La gracia del tutorial es el hecho de procesar los arrays para enviarlos a la base de datos. Si lo que necesitas son strings, hay que hacerlo como se hizo siempre.

      Me gusta

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s