Sistema de encuesta con AJAX

Veremos ahora un sistema de encuesta haciendo uso, como siempre de herramientas libres, de PHP + MySQL y AJAX. Las características de este sistema de encuesta son simples en realidad. Contendrá las siguientes partes: un administrador, para agregar una nueva encuesta o actulizarla; visualizador de opciones, la lista de alternativas con un boton de opción a su lado; visualizador de resultados, es decir las opciones con sus respectivos resultados; y el número de votantes.

Definamos la tabla y especificaremos, el porque de los campos y su tipo.

CREATE TABLE `encuesta` (
 `idenc` int(7) NOT NULL auto_increment,
 `pregunta` varchar(255) NOT NULL default '',
 `nrovotos` int(7) default '0',
 `opciones` text NOT NULL,
 `respuestas` text NOT NULL,
 KEY `id` (`idenc`)
 ) ENGINE=MyISAM;

Tenemos el campo idenc de tipo int autoincrement, es útil para identificar el registro de la encuesta; el campo pregunta tipo varchar, escribiremos allí la pregunta de la encuesta; nrovotos de tipo int, el numero de los votantes; opciones tipo text, las alternativas que puede elegir el votante; y finalmente el campo respuestas de tipo text también, almacena las respuestas a las alternativas seleccionadas.

Sobre los campos opciones y respuestas queremos aclarar un punto, vamos a trabajar de la siguiente manera: Las opciones que el usuario ingrese para su encuesta serán separadas por comas y se concatenarán para formar una sola expresión que se guardará en el campo opciones de tipo text. Lo mismo sucede para el campo respuestas, allí se guardará las cantidades de cada alternativa y luego se concatenarán para forma una sola expresión que se almacenará en el campo respuestas.

Pongamos un ejemplo, tenemos la siguiente encuesta:

¿Qué te parece el tutorial de Sistema de Encuesta?

  • Muy bueno
  • Bueno
  • Regular
  • Malo

Siguiendo el ejemplo, nuestro sistema de encuesta tiene que almacenar las alternativas: “Muy bueno, Bueno, Regular, Malo” en el campo opciones, y automaticamente tiene que crear las respuestas iniciales, en este caso: “1,1,1,1”, o sea una unidad por cada opción. De manera que cuando un usuario eliga una alternativa se sumará una unidad a cada opción elegida. Ej. Si el usuario elige “Muy bueno”, entonces las respuestas tienen que quedar así: “2,1,1,1”. Espero que de momento este algo claro, pero a medida que explicare el código se podrá entender mejor.

Entonces vamos al código

conexion.php >> Datos de la conexión a la base de datos.

<?php
   //Configuracion de la conexion a base de datos
   $bd_host = "localhost";
   $bd_usuario = "root";
   $bd_password = "";
   $bd_base = "wordpress";
   $con = mysql_connect($bd_host, $bd_usuario, $bd_password);
   mysql_select_db($bd_base, $con);
?>

admin.php >> Vamos a trabajar con un solo registro; es decir, creamos un encuesta y si deseamos cambiar la pregunta y las opciones simplemente actualizamos los datos. Desde está pagina podremos hacer esto, agregaremos una encuesta si no existe o actualizaremos la actual.

La página contiene un formulario con dos campos, uno para agregar la pregunta y otro para las opciones las cuales debemos separar por coma (,). El código PHP trabaja de la siguiente manera: capturamos las variables pregunta y opciones mediante el método POST, luego aplicamos explode a las opciones para separar los elementos por coma, así automaticamente creamos un array, luego contamos los elementos del array y mediante un while especificamos una cadena de texto de este tipo “1,1,1,1”. Luego verificamos si existe encuestas en la base de datos, dependiendo de si existe o no, actualizará o agregará una.

Nota: No creamos cadena de respuestas de este tipo “0,0,0,0,0”, porque cuando trabajamos con cero genera un error al pasar de texto a número y viceversa, así que cuando iniciamos una encuesta la hacemos con “1,1,1,1”. Por supuesto, la cantidad de unos dependerá de las opciones.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Mini-Administrador de encuesta</title>
</head>
<body>
<?php
  require('conexion.php');
  $continuar=false;
  if(isset($_POST['pregunta'])) $continuar=true;
  if(isset($_POST['opciones'])) $continuar=true;
  if($continuar==true){
    $pre=$_POST['pregunta'];
    $opc=$_POST['opciones'];
    $opciones = explode(",",$opc);
    //contamos cantidad de elementos
    //separados por coma
    $tot_elems=count($opciones);
    //iniciamos variables que usaremos
    $coma="";
    $i=0;
    $unidad="1";
    $respuesta="";
    //escribimos cadena del tipo "0,1,0,0,0"
    while($i<=$tot_elems-1){
       $respuesta=$respuesta.$coma.$unidad;
       $coma=",";
       $i++;
    }
    //verificar si existe encuesta la actualizamos
    //sino la registramos
    $cons_cant=mysql_query("SELECT COUNT(*) AS nroenc FROM encuesta",$con);
    $cant=mysql_fetch_array($cons_cant);
    if($cant['nroenc']==0){
       $insenc="INSERT INTO encuesta(pregunta, opciones, respuestas) VALUES ('$pre','$opc','$respuesta')";
       $insencresult = mysql_query($insenc, $con);
       echo "<div style=\"background-color:#888888;width:200px;color:red;\">Agregado <a href=\"./\">Ver encuesta</a></div>";
    }else{
       $cons_id=mysql_query("SELECT idenc FROM encuesta",$con);
       $idenc=mysql_fetch_array($cons_id);
       $id=trim($idenc['idenc']);
       $updenc="UPDATE encuesta SET pregunta='$pre', opciones='$opc', respuestas='$respuesta', nrovotos=0 WHERE idenc=$id";
       $updencresult = mysql_query($updenc, $con);
       echo "<div style=\"background-color:#888888;width:200px;color:red;\">Modificado <a href=\"./\">Ver encuesta</a></div>";
    }
  }
?>
<h3>Mini-Administrador de encuesta</h3>
<form name="frmEncuesta" method="post" action="admin.php">
<p>Escriba la pregunta</p>
<p>
  <input name="pregunta" type="text" id="pregunta" />
</p>
<p>Escriba las opciones separandolas por comas. Ej. Ubuntu, Red Hat, Suse, Debian</p>
<p>
  <input name="opciones" type="text" id="opciones" />
</p>
<p>
  <input type="submit" name="Submit" value="Crear Encuesta" />
</p>
</form>
</body>
</html>

index.php >> Ahora la página inicial de la encuesta. Esta página muestra la pregunta de la encuesta y las opciones que podemos elegir con un botón en la parte final para votar.

El script funciona así: Verificamos en primer lugar si existe la encuesta, en caso de no existir mostramos un vinculo que nos lleva a la página admin.php, en caso de existir realizamos otra consulta para capturar los datos de la tabla encuesta en varibles. Pasamos a definir un formulario en cuyo evento onsubmit espeficiamos la función cargarResultados(), esta función se encuentra en el archivo funciones_javascript.js. Usamos explode para separar las las opciones por coma para luego contar cuantos son y mediante un while creamos los botones radio necesarios. Recordemos que al usar explode convertimos una variable en array, así que para ver lo que contiene este elemento usamos un contador en este caso $i. También especificamos input de tipo hidden con el cantidad de opciones, este dato lo usaremos en la función cargarResultados(). Finalmente al formulario le colocamos un botón con el texto Votar.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Sistema de encuesta</title>
<script language="javascript" type="text/javascript" src="funciones_javascript.js"></script>
</head>
<body>
<?php
  require('conexion.php');
  //consultamos si hay datos en la tabla
  $cons_cant=mysql_query("SELECT COUNT(*) AS nroenc FROM encuesta",$con);
  $cant=mysql_fetch_array($cons_cant);
  if($cant['nroenc']==0){
    echo "<p>No hay encuesta</p>";
    echo "<p><a href=\"admin.php\">Agregar encuesta</p>";
  }else{
    //consultamos la encuesta actual
    $cons_enc_act=mysql_query("SELECT * FROM encuesta",$con);
    $datos=mysql_fetch_array($cons_enc_act);
    //obtenemos los datos de la tabla
    $id=$datos['idenc'];
    $preg=$datos['pregunta'];
    $opc=$datos['opciones'];
    //empezamos a crear la estructura html
    echo "
    <p style=\"padding-bottom:10px;\"><strong>".$preg."</strong></p>
    <div id=\"resultados\"> \n";
    //especificamos un formulario
    echo "
    <form onsubmit=\"cargarResultados(); return false\" name=\"frmencuesta\" action=\"\">
    <input type=\"hidden\" name=\"cod\" value=\"".$id."\" /> \n";
    //especificamos opciones
    //NOTA, usamos explode para separar cada item por las comas
    $opciones = explode(",",$opc);
    $i=0;
    //contamos cuantas partes tiene opciones
    $tot_elems=count($opciones);
    while($i<=$tot_elems-1){
      $j=$i+1;
      //note que $opciones es un array y visualizamos sus elementos
      //mediante esta forma: elemento=$opciones[ubicacion_integer]
      echo "
      <p>
      <input type=\"radio\" name=\"opcion\" value=\"".$j."\" id=\"opcion".$j."\" /> ".trim($opciones[$i])."</p> \n";
      $i++;
    }
    echo "
    <input type=\"hidden\" name=\"nroopciones\" value=\"".$i."\" />";
    echo "
    <p style=\"text-align:center;\">
      <input class=\"boton\" type=\"submit\" value=\"Votar\" />
    </p>
    </form>
    </div> \n";
}
?>
</body>
</html>

funciones_javascript.js >> Definimos aquí las funciones: nuevoAjax() para crear el objeto XMLHttpRequest, y cargarResultados() la cual se encarga de verificar mediante un while si algun boton radio está seleccionado (checked), si es así capturamos en la variable alt el numero. Luego especificamos el archivo que realizará el proceso resultados.php, y le enviamos dos variables el id de la encuesta y la alternativa seleccionada.

function nuevoAjax(){
   var xmlhttp=false;
   try{
     xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
   }catch(e){
     try{
       xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
     }catch(E){
       xmlhttp=false;
     }
 }
 if(!xmlhttp && typeof XMLHttpRequest!='undefined'){
   xmlhttp = new XMLHttpRequest();
 }
 return xmlhttp;
}
function cargarResultados(){
   divResultado = document.getElementById('resultados');
   //obtengo el codigo de la encuesta
   codenc=document.frmencuesta.cod.value;
   //obtengo el numero de opciones
   nroopc=document.frmencuesta.nroopciones.value;
   //creo un bucle para ver si alguna opcion esta checked
   //si esta checked ese valor lo envio por post
   i=1;
   while(i<=nroopc){
      opcion=document.getElementById('opcion'+i).checked;
      if (opcion==true){
         alt=i;
      }
      i++;
   }
   ajax=nuevoAjax();
   ajax.open("POST", "resultados.php",true);
   ajax.onreadystatechange=function() {
      if (ajax.readyState==4) {
         divResultado.innerHTML = ajax.responseText
      }
   }
   ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
   //envio dos valores el id de la encuesta y la opcion elegida de la encuesta
   ajax.send("idenc="+codenc+"&alternativa="+alt)
}

resultados.php >> Este el archivo principal del proceso de la encuesta. Su función es actualizar las opciones elegidas y mostrar los totales hasta el momento.

¿Como funciona? Obtengo las variables que me envio la función javascript cargarResultados(), el id de la encuesta y la alternativa seleccionada, luego realizamos una consulta por su id para trabajar con los valores obtenidos. Mediante explode separamos por coma los elementos tanto de las opciones como de las respuestas, contamos cuantos elementos son y mediante un while vamos concatenar la nueva respuesta. Esto lo haremos así: por ejemplo supongamos que se envio la alternativa 3, dentro del while mediante un if compararemos si son iguales, en caso afirmativo le sumaremos una unidad. Al final concatenaremos todas las respuestas. Después realizamos un update para actualizar tanto las respuestas como el número de votos.

Ahora listar los resultados. Para ello consultamos los nuevos datos, capturamos las variables con las cuales trabajaremos y separamos por coma las opciones y respuestas. Usamos un while para listar las opciones con su respectiva respuesta. Vamos a mostrar la alternativa con su porcentaje. Hay que tener en cuenta que para sacar el porcentaje a la respuesta le restamos una unidad, esto porque cuando guardamos la primera vez lo hicimos con 1,1,1… Finalmente mostramos el total de votos.

<?php
   require('conexion.php');
   //obtengo posicion de la opcion elegida
   $id=$_POST['idenc'];
   $vot=$_POST['alternativa'];
   //consulto la encuesta enviada
   $consulta=mysql_query("SELECT * FROM encuesta WHERE idenc=$id",$con);
   $datos=mysql_fetch_array($consulta);
   $opc=$datos['opciones'];
   $resp=$datos['respuestas'];
   //opciones aqui
   //explode separa c/item por las comas
   //aqui creamos automaticamente un array
   //con los elementos separados por coma
   $opciones = explode(",",$opc);
   $rptas = explode(",",$resp);
   $i=0;
   //iniciamos variables de cadenas vacias
   $respuesta_nueva="";
   $alternativas="";
   $coma="";
   //contamos la cantidad de respuestas
   $tot_elems=count($rptas);
   while($i<=$tot_elems-1){
      $j=$i+1;
      //si la opcion elegida coincide con el elemento
      //sumamos 1 a la opcion
      if($j==$vot){
         $valor_respuesta=$rptas[$i]+1;
      }else{
         $valor_respuesta=$rptas[$i];
      }
      //escribimos cadena del tipo "0 1 0 0"
      $respuesta_nueva=$respuesta_nueva.$coma.$valor_respuesta;
      $alternativas=$alternativas.$rptas[$i];
      $coma=",";
      $i++;
   }
   //actualizamos a nuevos valores de respuestas, y sumamos en una unidad el numero de votos
   $updenc="UPDATE encuesta SET respuestas='$respuesta_nueva', nrovotos=nrovotos+1 WHERE idenc=$id";
   $updencresult = mysql_query($updenc, $con);
   //ahora listamos resultados
   $consulta2=mysql_query("SELECT * FROM encuesta WHERE idenc=$id",$con);
   $listado=mysql_fetch_array($consulta2);
   $preg=$listado['pregunta'];
   $opc=$listado['opciones'];
   $resp=$listado['respuestas'];
   $nrovot=$listado['nrovotos'];
   $opciones = explode(",",$opc);
   $rptas = explode(",",$resp);
   $i=0;
   $tot_elems=count($opciones);
   while($i<=$tot_elems-1){
      echo "<p>";
      echo $opciones[$i];
      $ResulOpc = $rptas[$i]-1;
      //-1 por que empieza con 1 en los resultados
      //esto por que si coloco 0 (ceros) no acepta
      //total de votos por cada opcion por el 100% y sobre el numero total de votos
      $ResulPorc=( $ResulOpc * 100 ) / $nrovot;
      echo "&nbsp;<strong>".round($ResulPorc,2)."%</strong>";
      echo "</p> \n";
      $i++;
   }
   echo "<p style=\"text-align:center;\">Total de votos: ".$nrovot."</p> \n";
?>

He incluido lineas //comentadas en el código con el fin de explicar mejor cada bloque de código y que pueda ser entendido. Pueden ver una muestra en acción y como también descargar el código.

El sistema de encuesta se puede mejorar a criterio de cada uno. Por ejemplo para no realizar votos a cada instante se puede trabajar con cookies o guardar las IPs.

19 thoughts on “Sistema de encuesta con AJAX

  1. Enhorabuena y muchas gracias por el artículo, es muy didáctico y sencillo.
    Sólo una pregunta: ¿cómo podría añadirle la funcionalidad de que una misma persona pueda votar sólo una vez?

  2. Puedes trabajar con cookies en php o guardar la ip del visitante en una tabla. No profundice en esto, porque hay mucha info al respecto en la web. Pero quizás hable de ello mas adelante.

  3. Si tengo lo siguiente:
    ——————————————————————————————-
    boton_radio|nombre|edad|numero_modificar
    ——————————————————————————————-
    Cómo hago para que haciendo click en el botón de radio se escoja todo el registro para borrarlo o modificarlo, mediante rutinas llamadas con un botón submit para cada rutina.

  4. Hola, estoy con un pequeñísimo detalle (valga el sarcasmo) referente a realizar lo siguiente, tengo una tabla con X cantidad de registros y al final de cada uno hay un checkbox para que el usuario pueda seleccionar los que desee, al hacerlo logré mostrar en pantalla los códigos seleccionados, pero ahora necesito mostrar en un documento pdf, todos los códigos con sus demás datos, ellos están almacenados en una bd postgre, mi pregunta específica es: como hacer que el select me reconozca la variable que contiene los códigos seleccionados?? hasta ahora estoy trabajando con implode y explode para ello, y 2do, como debería ser el ciclo para mostrar dichos registros, y dos debería crear un ciclo para autoincrementar las filas de la tabla que se va formando con cada registro añadido??? Espero puedas darme una lucecita con algún ejemplo o algo parecido… De antemano gracias por lo que puedas hacer por mi
    Carol

  5. Hola me sale un error que no me deja mostrar los resultados, creo ke no esta validada la division entre zero:
    Warning: Division by zero in C:AppServwwwEncuesta
    esultados.php on line 64

  6. muy bueno, le hice algunos cambios para usarlo en una BD de sql server 2005 y me funcionó a la perfeccion, gracias

  7. Hola! estoy probando el script y funciona bien, pero me gustaría que me dijeras como se podría hacer para restringuir el voto por IP, ya que no hay restricciones y la misma IP podría darse los votos que quisiera.
    Un saludo!

  8. hola amigos,
    soy nuevo en esto y quisiera un poco de orientacion, ¿como le podria hacer para no solo meter una pregunta a la vez? me gustaria poder poner todas las preguntas que quisiera con cada una de sus respuestas y despues poder mostrar y contestar todo en una sola pagina.
    Por cierto, el codgigo de esta pagina funciona al 100%
    Gracias por todo

  9. Tengo inconveniente me sale error en los echo “Parse error: syntax error, unexpected T_STRING, expecting ‘,’ or ‘;’ in C:\AppServ\www\encuesta\index.php on line 15”

  10. no mamen , dejen de decir que no sirve el script
    mejor aprendan a programar bola de huevones antes de andar criticando

  11. Hola a todos, estoy empezando en este mundo de la programación php y utilizando este sistema de encuesta lo hice tal y como dice aquí, primero que nada, no me esta guardando los datos en la base de datos, es decir la alternativa que yo selecciono, no varia en mi BD MySQL y a la hora de mostrar los resultados me da los siguientes errores
    Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /var/www/miguel/encuesta/resultados.php on line 8
    Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /var/www/miguel/encuesta/resultados.php on line 47
    Warning: Division by zero in /var/www/miguel/encuesta/resultados.php on line 64
    0%
    Alguien de los presente me puede ayudar por favor

  12. Espectacular estoy mejorandolo a mis necesidades con barra de porcentaje y algunas cosas mas….
    Gracias por el aporte de veras muchas gracias…

Leave a Reply

Your email address will not be published. Required fields are marked *

Proudly powered by WordPress | Theme: Wanderz Blog by Crimson Themes.