Procesar formularios múltiples con Ajax y PHP

  • Por
  • Ajax
Un ejercicio de envío y procesado de datos de formularios, con múltiples formularios por página, realizado por Ajax y con PHP usando la librería Xajax.
La idea de este artículo es profundizar un poco en el procesado y validación de formularios con Ajax y PHP, utilizando las librerías Xajax, que venimos explicando en el Manual de Xajax publicado en DesarrolloWeb.com. Esto ya lo estuvimos viendo en el artículo Enviar y procesar formulario con Ajax y PHP y los artículos siguientes a éste del manual.

En este caso, vamos a implementar un sistema de envío de formularios con estas diferencias:
  • Vamos a utilizar la versión de Xajax 0.5 (antes estábamos utilizando la versión 0.2 y con la 0.5 varias cosas han cambiado, como ya explicamos en el artículo Upgrade de Xajax 0.2 a 0.5.
  • En este ejemplo vamos a realizar un tratamiento de caracteres UTF-8, para decodificarlos y utilizarlos en páginas que utilizan el juego de caracteres ISO-8859-1. Por supuesto, utilizamos el método de propio de Xajax 0.5.
  • Por último vamos a introducir un procesamiento de múltiples formularios por página. En este ejemplo tendremos varios formularios en vez de uno y cada formulario servirá para actualizar un registro de una tabla de base de datos. Así permitiremos actualizar varios registros a través de la misma página.
Pues dicho esto, veamos primero la tabla de base de datos que vamos a actualizar por medio de los formularios.


Es una tabla donde se guarda información de países. En concreto tenemos el identificador y luego el nombre del país y la bandera. Tanto la bandera como el nombre son cadenas de texto.

En nuestro ejemplo tendremos una página con todos los formulario para actualizar desde un mismo sitio todos los países metidos en la tabla. Se mostrará un formulario por país y cada formulario se procesará de manera independiente, alternado el país que se haya editado. Los resultados se cargarán en la misma página, informando si hubo errores de validación o si se actualizaron los datos correctamente.

Construcción de los formularios

Vamos a hacer un bucle para crear un formulario por registro de la tabla. Cada formulario tendrá un identificador distinto, para saber cuál es y además estará metido dentro de una capa DIV, que también tendrá un identificador propio. Para generar identificadores distintos para cada elemento utilizaremos una variable $i para enumerar los formularios y las capas donde están.

Ahora podemos ver cómo se realiza un recorrido a todos los registros de la tabla, para crear un formulario por cada uno de ellos.

<?
//conecto con la base de datos
//este script está sobre mi instalación local de apache + php + mysql
$conn = mysql_connect ("localhost", "root", "");
//selecciono la base de datos con la que trabajar
mysql_select_db("dw");


$ssql = "select * from pais";
$rs = mysql_query($ssql);
$i=0;
while ($fila=mysql_fetch_object($rs)){
   $i++;
   echo '<div id=f' . $i . '><form id=form' . $i . '>
      <input type="hidden" name="formulario_origen" value="f' . $i . '">
      <input type="hidden" name="id_pais" value="' . $fila->id_pais . '">
      <input type="text" name="nombre_pais" maxlength="100" size=50 value="' . $fila->nombre_pais . '">
      <br>
      <input type="text" name="bandera" size=30 maxlength="30" value="' . $fila->bandera . '">
      <br>
      <input type="button" value="guardar" onclick="xajax_procesar_formulario(xajax.getFormValues(\'form' . $i . '\'))">
   </form></div>
   <div id=errorf' . $i . '></div>';
   echo "</p>";
}

mysql_close($conn);
?>


Nos podemos fijar que en cada formulario se incorporan dos campos hidden, uno con el nombre de la capa DIV donde está formulario de origen y otro con el identificador de país al que pertenecen los datos de ese formulario.

También hay que llamar la atención sobre el botón de envío del formulario, que no existe. En lugar del submit colocamos un botón normal que llama a una función xajax, que será la que se encargue de procesar el formulario. A esa función xajax le pasamos por parámetro los valores del formulario que debe procesar, que obtenemos por medio de la llamada al método Javascript xajax.getFormValues(), pasando a su vez el nombre del formulario.

Todo tiene sus respectivos identificadores, para poder referirnos a los formularios, las capas DIV que los contienen y la capa donde mostraremos los posibles mensajes de error.

Función Xajax para procesar el formulario

Esta función validará el formulario. Si hay errores de validación los mostrará y si no los hay intentará actualizar el registro de la base de datos. Si la sentencia SQL para actualizarlo falla, también mostrará el error y si se ejecuta correctamente avisará que se ha cambiado el registro.

function procesar_formulario($form_entrada){
   $respuesta = new xajaxResponse();
   //valido los datos
   $errores = "";
   if ($form_entrada["nombre_pais"] == ""){
      $errores = "Escribe un nombre de país";
   }elseif($form_entrada["bandera"] == ""){
      $errores = "Escribe el nombre de una imagen en el campo bandera";
   }
   
   if ($errores != ""){
      //hubo errores de validación en el formulario
      //muestro un mensaje de error.
      $salida="<b style='color:red;'>ERROR:</b>" . $errores;
      $respuesta->Assign("error" . $form_entrada["formulario_origen"],"innerHTML",$salida);
   }else{
      //si no tiene errores de validación el formulario
      $conn = mysql_connect ("localhost", "root", "");
      mysql_select_db("dw");
      $ssql = "update pais set nombre_pais='" . $form_entrada["nombre_pais"] . "', bandera='" . $form_entrada["bandera"] . "' where id_pais=" . $form_entrada["id_pais"];
       if (mysql_query($ssql)){
         $salida="<b style='color:green;'>OK!</b>";
         $respuesta->Assign($form_entrada["formulario_origen"],"innerHTML",$salida);
         $respuesta->Assign("error" . $form_entrada["formulario_origen"],"innerHTML","");
      }else{
          $salida="<b style='color:red;'>ERROR</b>";
         $respuesta->Assign("error" . $form_entrada["formulario_origen"],"innerHTML",$salida . "<span style='font-size:8pt'>" . mysql_error() . "</span>");
      }

      mysql_close($conn);
   }
//tenemos que devolver la instanciación del objeto xajaxResponse
return $respuesta;
}


La función recibe por parámetro los valores del formulario que se ha enviado, en un array asociativo. El código está comentado para que se entiendan los distintos pasos. Ahora bien, lo importante es que se vea que dependiendo de lo que ocurra en la función se actualizan unos elementos de la página, para mostrar posibles errores o para decir que todo ha sido correcto.

Tratamiento UTF-8 en Xajax 0.5

Los datos que nos vienen a través de Ajax llegan al servidor con el juego de caracteres UTF8. En Xajax existen unos modos de convertir esos caracteres a ISO, si es que estamos utilizando la codificación ISO-8859-1. En Xajax 0.5 el tratamiento de los datos en UTF-8 cambia con respecto a la versión 0.2. Ahora debemos indicar que trabajamos con ISO-8859-1, después de instanciar el objeto de la clase Xajax y además tenemos que especificar una variable de configuración para decodificar automáticamente los caracteres UTF-8.

$xajax = new xajax();
$xajax->setCharEncoding('ISO-8859-1');
$xajax->configure('decodeUTF8Input',true);


Todo el código junto

Os dejo el script completo, para que podáis seguirlo con mayor facilidad y de manera global:

<?
//incluímos la clase ajax
require ('../xajax/xajax/xajax_core/xajax.inc.php');

//instanciamos el objeto de la clase xajax
$xajax = new xajax();
$xajax->setCharEncoding('ISO-8859-1');
$xajax->configure('decodeUTF8Input',true);

function procesar_formulario($form_entrada){
   $respuesta = new xajaxResponse();
   //valido los datos
   $errores = "";
   if ($form_entrada["nombre_pais"] == ""){
      $errores = "Escribe un nombre de país";
   }elseif($form_entrada["bandera"] == ""){
      $errores = "Escribe el nombre de una imagen en el campo bandera";
   }
   
   if ($errores != ""){
      //hubo errores de validación en el formulario
      //muestro un mensaje de error.
      $salida="<b style='color:red;'>ERROR:</b>" . $errores;
      $respuesta->Assign("error" . $form_entrada["formulario_origen"],"innerHTML",$salida);
   }else{
      //si no tiene errores de validación el formulario
      $conn = mysql_connect ("localhost", "root", "");
      mysql_select_db("dw");
      $ssql = "update pais set nombre_pais='" . $form_entrada["nombre_pais"] . "', bandera='" . $form_entrada["bandera"] . "' where id_pais=" . $form_entrada["id_pais"];
       if (mysql_query($ssql)){
         $salida="<b style='color:green;'>OK!</b>";
         $respuesta->Assign($form_entrada["formulario_origen"],"innerHTML",$salida);
         $respuesta->Assign("error" . $form_entrada["formulario_origen"],"innerHTML","");
      }else{
          $salida="<b style='color:red;'>ERROR</b>";
         $respuesta->Assign("error" . $form_entrada["formulario_origen"],"innerHTML",$salida . "<span style='font-size:8pt'>" . mysql_error() . "</span>");
      }

      mysql_close($conn);
   }
//tenemos que devolver la instanciación del objeto xajaxResponse
return $respuesta;
}
$xajax->register(XAJAX_FUNCTION, 'procesar_formulario');

//El objeto xajax tiene que procesar cualquier petición
$xajax->processRequest();
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
   <title>Listado de breves</title>
   <?
   $xajax->printJavascript("../xajax/xajax/");
   ?>
</head>

<body>
<?
//conecto con la base de datos
//este script está sobre mi instalación local de apache + php + mysql
$conn = mysql_connect ("localhost", "root", "");
//selecciono la base de datos con la que trabajar
mysql_select_db("dw");


$ssql = "select * from pais";
$rs = mysql_query($ssql);
$i=0;
while ($fila=mysql_fetch_object($rs)){
   $i++;
   echo '<div id=f' . $i . '><form id=form' . $i . '>
      <input type="hidden" name="formulario_origen" value="f' . $i . '">
      <input type="hidden" name="id_pais" value="' . $fila->id_pais . '">
      <input type="text" name="nombre_pais" maxlength="100" size=50 value="' . $fila->nombre_pais . '">
      <br>
      <input type="text" name="bandera" size=30 maxlength="30" value="' . $fila->bandera . '">
      <br>
      <input type="button" value="guardar" onclick="xajax_procesar_formulario(xajax.getFormValues(\'form' . $i . '\'))">
   </form></div>
   <div id=errorf' . $i . '></div>';
   echo "</p>";
}

mysql_close($conn);
?>


</body>
</html>


Eso es todo. Espero que se haya podido entender bien este script y que sirva como ejemplo de uso para guiar tus pasos con Ajax y PHP. Cuando publico un artículo en desarrolloweb.com me gusta siempre ofrecer un enlace para ver el ejemplo en marcha, pero en este caso me lo he saltado. Me tendréis que disculpar. Espero que eso no dificulte la comprensión de lo que hace este script. Insisto que lo importante es sacar detalles de uso de Xajax que te den ideas para implementar tus propios sistemas Ajax con PHP.

Autor

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

Eric P

16/10/2008
Hice algunas modificaciones a tu código, y traté también de usar una base de datos de respaldo, para no crear una nueva.

Pero el resultado fue: Fatal error: Call to a member function processRequest() on a non-object in /home/epizarro/public_html/Principal/PruebaXajax2.php on line 39

Por mas que miro la línea, no entiendo que me está diciendo. Puedes ayudarme? Soy nuevo con php y xajax.

Saludos y gracias.

David

21/10/2008
Excelente, toda la aportación que haceis en todos los temas. Excelente. Ánimo y seguid asi. Gracias.

nicolas

12/11/2008
www.libroswebs.es
www.librosweb.es

hay un manual no tan completo para inicializarce con ajax y posteriormente crear la validacion y procesamiento de formulaios con php y XAjax

PHP ero

19/3/2009
tu codigo tiene un error en la linea 71, en el while

LaMir

25/1/2013
El formulario no me recoge un valor
Hola!!
Antes de nada quería decir que éste tutorial me ha ayudado ¡MUCHÍSIMO! Me encanta porque yo sé muy poco de ésto y me ha venido muy bien. Ahí va el

atasco que tengo...

Son tres funciones:

1.- function form1 () que tiene el formulario múltiple. Funciona perfectamente.
2.- function procesar_descripcion() a la que le llegan parámetros del form1() y me los muestra perfectamente con un while. Cada descripción tiene un botón

para insertar una foto.
3.- formulario_foto() a la que le debería de llegar el parámetro de la descripción elegida pero sólo le llega el primero.

function form1($id_prov){
include("conexion.php");
$esp = "SELECT *
FROM provincias
INNER JOIN municipios ON provincias.id_prov=municipios.id_prov
INNER JOIN lugares ON municipios.id_mun=lugares.id_mun";
$datos = mysql_query($esp, $conexion);
$i=0;
while ($fila=mysql_fetch_object($datos)){
$i++;
$salida .= '<div id=f' . $i . '>
<form id=form' . $i . '>
<input type="hidden" name="formulario_origen" value="f' . $i . '">
<input type="hidden" name="id_prov" value="' . $fila->id_prov . '">
<input type="hidden" name="id_mun" value="' . $fila->id_mun . '">
<input type="hidden" name="id_lugar" value="' . $fila->id_lugar . '">
<a onclick="xajax_procesar_descripcion(xajax.getFormValues('form' . $i . ''))">Descripciones</a>
</form>
</div>
<div id=desplegarf' . $i . '></div>
<div id=desplegardosf' . $i . '></div>';
$salida .= "<br>";
}
mysql_free_result($datos);
mysql_close($conexion);
return $salida;
}

function procesar_descripcion($form_entrada){
$respuesta = new xajaxResponse('ISO-8859-1');
include("conexion.php");
$ssql = "SELECT *
FROM descripciones
INNER JOIN temas ON descripciones.id_tema=temas.id_tema
WHERE id_lugar=" . $form_entrada["id_lugar"];
$datos = mysql_query($ssql, $conexion);

//Mostramos cada descripción con su correspondiente botón
while($row = mysql_fetch_array($datos)){
$salida .= '<form id=form' . $i . '>
<input type="text" name="formulario_origen" value="' . $form_entrada["formulario_origen"] . '">
<input type="hidden" name="id_prov" value="' . $form_entrada["id_prov"] . '">
<input type="hidden" name="id_mun" value="' . $form_entrada["id_mun"] . '">
<input type="hidden" name="id_lugar" value="' . $form_entrada["id_lugar"] . '">
<input type="text" name="id_descrip" value="' . $row["id_descrip"] . '">
<a onclick="xajax_formulario_foto(xajax.getFormValues('form' . $i . ''))">Insertar foto</a>
</form>';
}
$respuesta->addAssign("desplegar" . $form_entrada["formulario_origen"],"innerHTML",$salida);
mysql_close($conexion);
return $respuesta;
}

function formulario_foto($form_entrada){ // Una pista... us-editar.php y us-modificar-foto.php
//creo el xajaxResponse para generar una salida
$respuesta = new xajaxResponse('ISO-8859-1');

$codigo_formul = $form_entrada["id_descrip"];
// sólo me muestra el primer parámetro de $row["id_descrip"], aunque pinche en otro de otra descripción

//mostramos en capa capaformulario el texto código HTML del formulario
$respuesta->addAssign("desplegardos" . $form_entrada["formulario_origen"],"innerHTML",$codigo_formul);
return $respuesta;
}

De verdad que lo he REQUETEmirado y no entiendo qué puede pasar. Será alguna tontería.
Gracias y un saludo.
Miriam

LaMir

25/1/2013
El formulario no me recoge un valor
Lo siento, se me ha colado algo que no significa nada:

// Una pista... us-editar.php y us-modificar-foto.php

Ni caso, son cosas mías.

no sirve

21/1/2015
nada no funciona
Siempre hay algún tipo de desperfecto en tus codigos