Encuesta simple con PHP y jQuery

Encuesta simple con PHP y jQuery

Anteriormente (2010) les había compartido un artículo sobre como crear un sistema de encuestas utilizando PHP y Mysql. En esta ocasión utilizaremos ese conocimiento para hacer algo mas sencillo, un sondeo o encuesta de una pregunta para tu sitio web o proyecto.

Alguien puede decir, ¿por qué escribir sobre lo mismo?. No, no es lo mismo. En el artículo Sistema de encuestas básico en PHP y MySql creamos un sistema o plataforma independiente de encuesta que puede ser enviado como un URL en un email, un enlace en tu sitio web, en la redes sociales, etc., por ejemplo como SurveyMonkey.

En esta ocasión haremos una encuesta simple para integrarlo a un website o una aplicación basada en Web, como esas que aparecen el los diarios electrónicos, sitio web de proveedores de servicio o en Twitter, si, en Twitter puedes hacer encuestas.

1. Base de Datos

Iniciamos con la estructura de datos o base de datos donde almacenaremos la encuesta y los votos. Para la encuesta necesitaremos tres tablas, una para el identificador o id de la encuesta o pregunta y el título de la misma. Una segunda tabla para las opciones o posibles respuestas a presentar para cada pregunta o encuesta y tercero una tabla para almacenar los votos u opciones seleccionadas por los usuarios como voto.

Crearemos una base de datos, o pueden utilizar una existente y solo cambiar la referencia en el archivo de configuración que veremos mas adelante. Por ahora vamos a llamarla: poll.

Nuestra base de datos contendrá las siguientes tablas:

Tabla 1: poller (Para la pregunta o encuesta)

Como les mencionaba en la introducción esta primera tabla contendrá la pregunta de la encuesta y el id de la misma para enlazar las opciones y votos.

Tabla 2: poller_option (Para las opciones de la pregunta o sondeo)

En esta segunda tabla, almacenaremos los opciones y a qué pregunta corresponden, ya que presentaremos varias opciones de respuesta a los usuarios, desde un simple si o no, hasta opciones múltiples. ID es un campo de indexación en este caso para manejar la relación opción -> voto. PollerID es el ID de la pregunta para la relación pregunta->opciones. PollerOrder puede ser utilizado para organizar en orden en que se presentan las opciones, creame esto influye en la respuesta de los usuarios. Por último defaultChecked, este campo nos puede servir si deseamos seleccionar una opción como indicadora o pre-seleccionada, esto se le llama inducción, o influir en la selección del usuario. Esto se emplea con frecuencia en encuestas sobre un servicio prestado.

Tabla 3: poller_vote (Votos o selección de respuesta del usuario)

En esta tercera tabla capturaremos los votos o selección de respuesta de los usuarios. Nótese el campo ipAddress, con este campo almacenaremos el IP del usuario al momento de votar. De esta forma podemos activar o no la opción de limitar un voto por usuario, claro, no es una forma completamente garantizada; pero puede servir ya que es muy poco probable que un usuario cambie su IP para hacer un voto, siendo el IP público un IP asignado por el proveedor de servicio de internet o telefonía y que muy raras veces cambia.

2. Conexión a la Base De Datos

Para esta encuesta utilizaremos OOP (Object Oriented Programming) o programación orientada a objetos, es decir, utilizaremos una clase para gestionar la información hacia y desde la base de datos. Como trabajaremos con OOP, utilizaremos PHP PDO como gestor de conexión de base de datos.

Entonces, tendremos nuestro archivo config.php o como quieran llamarle donde almacenaremos las credenciales de nuestro servidor de base de datos. En este definiremos constantes para referencia de los valores necesarios:

3. Modelo o Clase de gestión de datos

Una vez más, como utilizaremos una estructura OOP, crearemos una clase o librería la que llamaremos Polls.php con los métodos necesarios para: obtener la encuesta activa, obtener los resultados de la encuesta, capturar el voto del usuario y un método o función privada para saber si el usuario ya ha votado previamente basado en su dirección IP.

Vamos a ver nuestra clase en detalle para explicarles las propiedades cada método en ella:

Primero, hemos declarado nuestra clase con el nombre Application_Model_Polls, pueden utilizar cualquier nombre para la case, sin embargo, para mejor control y mantenimiento, recomiendo utilizar una estrucutra de etiquetas y formato “CamelCase” para identificar a quien pertenece, que es, y que contiene en el nombre. Así, con solo leer el nombre sabremos que es lo que estamos viendo en cualquier controlador o cualquier fichero donde hagamos referencia a nuestra encuesta.

Una vez declarada la clase, encontramos una serie de propiedades:

Estas propiedades, como su nombre de declaración lo indican, nos servirán para utilizar la conexión a la base de datos por medio de PDO y una variable $conn para definir la conexión misma dentro de la clase y $error para capturar cualquier error que se genere.

Luego encontramos el método __construct() que aunque está vacío, lo incluyo como referencia si queremos utilizar una conexión ya existente en nuestro proyecto.

Método getPoll();

Entonces encontramos la función getPoll(); Este método nos permite consultar la encuesta activa o en este caso la más reciente de nuestra tabla para mostrarla. Es decir, la pregunta y las opciones relacionadas a la pregunta para ser presentadas al usuario.

Nótese que empleamos try and catch para depurar nuestro código, tener mejor control y saber que sucede al momento de depurar y como bootstrap para la consulta misma, de forma que no destruya nuestro código general y así evitar un error que nos impida seguir mostrando el contenido de nuestro sitio o proyecto a pesar de que la encuesta falle.

Hemos utilizado el gestor PDO como gestor ya estable y depurado con que contamos en PHP 5 y superior. Consultamos si tenemos un parámetro “pollid”, en caso de que deseemos mostrar una encuesta en específico y no la más reciente, es un plus ;), de nuestra tabla poller.

Luego de tener el título y el ID de la pregunta, consultaremos todas las opciones disponibles para la pregunta en la tabla poller_option y creamos un array con el código de espuesta (code), basado en los códigos de respuesta de HTTP, seguido un array poll, con el ID y la pregunta de la encuesta y por último un array con las opciones disponibles. Esto se conoce como array o matriz anidado o bidimencional en este caso para facilitarnos el proceso de mostrar y manejar la información la cual retornamos como una estructura jSON json_encode(). Recuerden, estaremos trabajando con jQuery para la experiencia de usuario, y nada mejor que jSON para manejar datos estructurados.

Método getPollResults();

Para presentar los resultados de la encuesta basado en los votos obtenidos, debemos consultar la encuesta, las opciones y los votos obtenidos y contar los votos por cada opción para conocer los resultados de la encuesta parcial o final y para mostrarla al usuario una vez que este realice su voto.

Una vez más, pasamos el parámetro pollID para conocer el id específico de la pregunta o encuesta y poder obtener las opciones y votos relacionados a esta u obtener esta información de la última encuesta creada.

La igual que el método anterior, el retorno será un array bidimencional en estructura jSON de la matriz resultante con el código HTTP de respuesta, la pregunta y id de la encuesta y los resultados, que en este caso son las opciones de la pregunta y la cantidad de votos recibidos por cada una “COUNT(v.ID) as votes” de nuestra consulta SQL.

Método castVote();

Este método requiere dos parámetros o valores para capturar el voto del usuario: el id de la pregunta o encuesta y el id de la opción seleccionada por el usuario. (pollId, optionId). Internamente capturamos la dirección IP del usuario con la variable $_SERVER[‘REMOTE_ADDR’] para “garantizar” un voto por usuario. Esto puede desabilitarse simplemente pasando un valor NULL en caso de quere una encuesta abierto con multiples votos por usuario o, crear un método separado para limitar la cantidad de votos por IP o cualquier otra idea de como necesitemos gestionar los votos en nuestra encuesta.

Aquí nos encontramos con una condición basada en el método hasVoted, que describiremos a continuación. Este método nos ayudará a validar el voto del usuario.

Método hasVoted();

Esta función privada, solo puede usarse dentro de la clase misma, nos permitirá controlar un voto por usuario por encuesta, consultando el id de la encuesta y la dirección IP del usuario, buscando un registro en la tabla poller_vote. Si existe un registro con ambas condiciones, entonces significa que el usuario ya ha votado en la encuesta actual. Devolveremos un booleano (true, false) para saber si existe o no el voto.

4. Controlador de la encuesta (controller)

Nos permitirá consultar el método indicado según la acción del usuario e indicar que pregunta o encuesta queremos presentar. Así como intermediario entre el modelo y la vista o la forma en que el usuario interactúa con la encuesta, es decir, será la URL que utilizaremos en nuestro javascript. Permitiendo esto, libre control de como presentar la encuesta.

Vamos a crear un archivo en nuestro folder de controladores y lo llamaremos poll.php, donde llamaremos el archivo config.php por medio de include() o require_once(). Llamaremos el archivo que contiene la clase de nuestra encuesta y declararemos el objeto con el cual trabajaremos para mostrar tanto la encuesta como los resultados y capturar el voto del usuario. Todo en uno.

Entonces nuestro archivo poll.php contiene lo siguiente:

Como vemos, en el archivo controlador hacemos tres cosas:

Primero, incluimos el archivo de configuración config.php y el archivo con la clase Polls.php por medio de requiere_once(); el orden es importante, primero config.php para cargar las constantes definidas con las credenciales de la base de datos y luego la clase que utiliza estas constantes en el gestor PDO, no al revés, o tendremos un error.

Segundo, declaramos un nuevo objeto para gestionar nuestros métodos $polls = new Application_Model_Polls. Es importante que el nombre del objeto sea el mismo que el de la clase. Por eso les decía lo importante del nombre, así podemos tener varios objetos diferentes en un controlador y con solo ver el nombre sabremos de que se trata.

Tercero, tenemos una condición if…else… que nos permitirá saber si el usuario esta realizando la acción de votar o seleccionar su opción o si simplemente presentar la encuesta al usuario, capturando la variable $_POST. En este caso option que es el id de la opción o respuesta, aunque podemos hacerlo con el id de la encuesta y el id de la opción al mismo tiempo.

Filtramos las variables para eliminar cualquier XSS o uso indebido sabiendo que, los valores que esperamos son números enteros (ID).

De no existir la variable $_POST[‘option’], significa que el usuario no está votando castVote(), entonces, mostraremos la encuesta, getPoll().

Presentamos el resultado con print_r() y luego salimos: exit; para finalizar la ejecución de nuestro controlador.

5. HTML

Como la idea es presentar una encuesta simple, una pregunta con sus opciones de respuesta, en nuestro website, blog, web app o lo que sea en que necesites contar con una encuesta simple. Necesitaremos un bloque donde mostrarlo.

Esto lo hacemos creando una capa o contenedor, en este caso utilizaremos un <DIV> con el id “featured-poll”. Entonces tendremos este código el cual colocaremos donde queremos mostrar la encuesta:

Eso esto todo. Si, con una simple línea de html podemos implementar nuestra encuesta. Recuerda que utilizaremos jQuery como gestor de interacción de la misma.

6. Javascript y jQuery

Como presentaremos la encuesta en nuestro website, ahora necesitamos crear las funciones javascript necesarias para mostrar y capturar la encuesta. Para esto necesitaremos dos llamados $.ajax() uno con GET para mostrar la encuesta y otro POST para capturar el voto del usuario. Finalmente una funcion javascript para crear una barra horizontal que muestre la relación de votos o procentaje segun el total de votos por opción ¿Recuerdan esto de nuestra clase Polls.php?

Vamos a crear un archivo .js lo llamaremos poll.js donde colocaremos nuestro código javascript y la implementación de jQuery $.ajax:

En el código javascript tenemos lo siguiente:

Primero, un llamado GET que se ejecuta la cargar la página o sitio web. Este llamado $.ajax es para desplegar la encuesta por medio del llamado a nuestro controlador poll.php. En este caso no pasamos ningún parámetro, de forma que el controlador poll sea quien decida que encuesta mostrar según nuestra declaración de objeto.

Por medio del ID del bloque o elemento div al que le dimos el valor “featured-poll” hacemos referencia para que el resultado del llamado $.ajax pueda ser insertado en el HTML. De esta forma creamos nuestra estructura html de como queremos que se muestre la encuesta, permitiéndonos total control de la apariencia, para lo que nos ayuda jQuery.

En algunos casos he visto que la estructura html ya viene procesada en el modelo o clase php. Sin embargo, esto limita mucho que podamos reutilizar la encuesta y adaptarla a diferentes estructuras y páginas dentro de nuestro sitio, incluso para una versión móvil independiente de nuestro sitio.

El segundo llamado es un evento on(‘sumbit’). Como hemos colocado un botón en nuestro llamado GET para presentar la encuesta y como medio de acción para capturar el voto del usuario. Utilizaremos la propiedad submit para enviar el voto del usuario al controlador ($_POST en nuestro archivo poll.php de la condición if..else).

De igual forma, procesamos el resultado (data) que devuelve nuestro controlador en forma de jSON y colocamos esta información de respuesta con una estructura HTML según la forma en que queremos presentar los resultados de la encuesta una vez procesado el voto.

Aquí, tenemos un div o capa cuyo ID tiene el prefijo “bar-” y la clase progressBar. Este div nos permitirá presentar una barra del color que deseemos con el porcentaje en relacion al 100% del total de votos por cada opción.

Finalmente tenemos la función javascript progress(). Esta función nos ayuda a convertir el total del votos de cada opción a valor porentual en relación al ancho (width) que tenemos disponibles según nuestra capa HTML featured-poll. A la vez creamos un efecto de animación para llenar la barra horizontalmente con un color sólido indicador del porcentaje de la opción. Otro plus, no es necesario animarla pero se ve bien.

Esta función javascript progress toma el el div con la clase progressBar para presentar la barra animada según el id del elemento u opción como lo declaramos en la llamada del “on(‘submit’)”.

7. CSS

Por último, pero no menos importante, tenemos el CSS (Cascading Style Sheet) que nos ayudará a dar forma y color a nuestra encuesta:

Con el CSS podemos dar forma y color a nuestra encuesta ya sea de forma inline <style>…</style> o por referencia a un acrchivo css externo por <link />: <link href=”style.css” rel=”stylesheet” type=”text/css”> en nuestro sitio web.

Pueden jugar con el CSS para personalizar aún más la presentación de la encuesta de modo que siga el diseño y paleta de colores de su sitio web.

Pongan todo junto y prueben esta encuesta simple para websites, blogs o web apps.

Para administrar sus encuestas lo pueden hacer con phpMyadmin o bien creando su propio sistema de administración RBAC o incorporando un nuevo módulo en su sistema actual para listar, editar y crear encuestas. También, pueden crear un plugin para WordPress o cualquier otro sistema CMS.

Espero les sea de utilidad y recuerden. CODE IS POETRY!