Palavra:   

Revista PHP / AJAX

Flávia Jobstraibizer

Analista de sistemas, DBA Mysql, PostgreSQL, Oracle, SQLServer e Firebird. Desenvolvedora de sistemas, e administradora de servidores FreeBSD. Conheça o site www.flaviajobs.com.br

Enquete Ajax com a classe Xajax

Neste artigo, vou abordar a construção de uma enquete dinâmica e administrável, utilizando como principal elemento, a classe XAJAX (http://www.xajaxproject.org/) .
Não se preocupe em copiar tudo, no final do artigo, você poderá baixar todos os exemplos deste artigo.

Em primeiro plano, tenho aqui, a organização de um banco de dados, onde serão armazenadas as perguntas e respostas. Utilizei no exemplo uma base de dados mysql, e duas tabelas:

Criei em um banco de dados existente (flaviajo_flaviateste) duas tabelas. São elas: enquetes e opções_enquetes, conforme o sql a seguir:

Vamos ao código.

CREATE TABLE `enquetes` (
`id` int(11) NOT NULL auto_increment,
`enquete_titulo` varchar(255) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Tabela de enquetes' AUTO_INCREMENT=1 ;

CREATE TABLE `opcoes_enquetes` (
`opcoes_id` int(11) NOT NULL auto_increment,
`enquetes_id` int(11) NOT NULL default '0',
`opcoes_titulo` varchar(255) default NULL,
`opcoes_num_votos` int(11) default '0',
`opcoes_ordem` int(11) default NULL,
PRIMARY KEY (`opcoes_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Tabela de opções de enquetes' AUTO_INCREMENT=1 ;

Assim sendo, temos um local para gravar as perguntas e respostas e para tal, fiz uma interface simples:

adm.php
<?php
require_once('../../Connections/testes.php');  //classe de conexão

function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue; switch ($theType) {
case "text":
$theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
break;
case "long":
case "int": $theValue = ($theValue != "") ? intval($theValue) : "NULL";
break;
case "double":
$theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL";
break;
case "date":
$theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
break;
case "defined":
$theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
break;
}
return $theValue;
} $editFormAction = $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
$editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
} // como envio o formulário para a mesma página, tenho este if conferindo
// a ação do mesmo.
/* Note que este INSERT está gravando a pergunta da enquete, que após gravada receberá um ID. (na tabela criada mais acima, lembrando que o campo id, é auto increment)*/
if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
$insertSQL = sprintf("INSERT INTO enquetes (enquete_titulo) VALUES (%s)",
GetSQLValueString($_POST['enquete_titulo'], "text")); mysql_select_db($database_testes, $testes);
$Result1 = mysql_query($insertSQL, $testes) or die(mysql_error());
}
?>

<html>
<head>
<title>Untitled Document</title>
</head> <body>
<table width="500" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><form action="<?php echo $editFormAction; ?>" method="post" name="form1" id="form1">
<table align="center">
<tr valign="baseline">
<td nowrap="nowrap" align="right">Pergunta:</td>
<td><input type="text" name="enquete_titulo" value="" size="52" /></td>
</tr>
<tr valign="baseline">
<td nowrap="nowrap" align="right">&nbsp;</td>
<td><input name="submit" type="submit" value="Cadastrar pergunta" /></td>
</tr>
</table>
<input type="hidden" name="MM_insert" value="form1" />
</form></td>
</tr>
</table>
</body>
</html>

Então temos o seguinte:
Uma página para inserir as perguntas

E seu respectivo resultado:

Continuando, será necessário agora, cadastrar as respostas possíveis para esta enquete cadastrada, cujo ID é 1.
No meu exemplo, criei uma página onde gravo uma pergunta por vez, assim, gravo quantas respostas eu quiser para a minha enquete. Você pode adaptar isso como desejar.

adm2.php
<?php require_once('../../Connections/testes.php');  ?>
<?php
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue;
switch ($theType) {
case "text":
$theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
break;
case "long":
case "int":
$theValue = ($theValue != "") ? intval($theValue) : "NULL";
break;
case "double":
$theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL";
break;
case "date":
$theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
break;
case "defined":
$theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
break;
}
return $theValue;
} $editFormAction = $_SERVER['PHP_SELF']; if (isset($_SERVER['QUERY_STRING'])) {
$editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
}
// aqui estamos inserindo as opções de respostas, para a pergunta que já foi cadastrada anteriormente.
// Sendo que o campo enquetes_id, deve ser igual ao campo id da tabela enquetes. // Isso mostrando que essa opção de resposta é daquela enquete.
// O campo opcoes_ordem, trata de dizer posteriormente ao script ajax, em que ordem as // perguntas devem aparecer!
// portanto utilize a ordem desta forma 1,2,3, etc, sendo o 1 a prioridade mais alta.

if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
$insertSQL = sprintf("INSERT INTO opcoes_enquetes (enquetes_id, opcoes_titulo, opcoes_ordem) VALUES (%s, %s, %s)",
GetSQLValueString($_POST['enquetes_id'], "int"),
GetSQLValueString($_POST['opcoes_titulo'], "text"),
GetSQLValueString($_POST['opcoes_ordem'], "int")); mysql_select_db($database_testes, $testes);
$Result1 = mysql_query($insertSQL, $testes) or die(mysql_error());
} mysql_select_db($database_testes, $testes);
$query_verperguntas = "SELECT * FROM enquetes";
$verperguntas = mysql_query($query_verperguntas, $testes) or die(mysql_error());
$row_verperguntas = mysql_fetch_assoc($verperguntas);
$totalRows_verperguntas = mysql_num_rows($verperguntas); ?>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head> <body>
<table width="500" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<form method="post" name="form1" action="<?php echo $editFormAction; ?>">
<table align="center">
<tr valign="baseline">
<td nowrap align="right">Respostas para a pergunta:</td>
<td><select name="enquetes_id">
<?php
do {
?>
<option value="<?php echo $row_verperguntas['id']?>" > <?php echo $row_verperguntas['enquete_titulo']?></option>
<?php
} while ($row_verperguntas = mysql_fetch_assoc($verperguntas));
?>
</select> </td>
<tr valign="baseline">
<td nowrap align="right">Resposta::</td>
<td><input type="text" name="opcoes_titulo" value="" size="32"></td>
</tr> <tr valign="baseline">
<td nowrap align="right">Ordem da resposta: :</td>
<td><input type="text" name="opcoes_ordem" value="" size="32"></td>
</tr>
<tr valign="baseline">
<td nowrap align="right">&nbsp;</td>
<td><input type="submit" value="Cadastrar pergunta"></td>
</tr>
</table>
<input type="hidden" name="MM_insert" value="form1">
</form>
<p>&nbsp;</p></td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</table> </body>
</html>
<?php
mysql_free_result($verperguntas);
?>

Teremos então uma página cadastrando as respostas para a enquete:

Resultados cadastrados:


Note sempre que o campo enquetes_id mostra o id da pergunta que eu cadastrei no início!
Note também que o campo opções_num_votos que agora está zerado, será o campo atualizado pelo ajax, como veremos mais a frente.

Agora vamos ao resultado. O arquivo enquete.php é o arquivo que mostra ao usuário a última enquete cadastrada.

enquete.php
<?php
//arquivo de conexão do banco de dados
require_once("includes/config.php"); // Vou usar sessão apenas pra deixar a pessoa voltar uma vez, // e pelo menos enquanto o browser estiver aberto
@session_start();
// nome da sessão: isso é importante pra diferenciar sistemas // que rodam no mesmo servidor session_name(NOME_SESSAO); require_once("includes/functions.php"); // Comandos AJAX (olhe, mas não mexa... :) )
require("ajax/enquete.common.php"); // Imprime os códigos javscript da classe Xajax para a página
$xajax->printJavascript("libs/xajax/");
?>

<!-- Esse id na DIV é importante. É através dele que vamos trazer os resultado da enquete -->
<div id="div_enquete"> <?php // Faz a busca pela última enquete gravada do banco de dados
// Isso é útil, já que você poderá trocar a enquete posteriormente, sem nem mesmo
// ter de abrir o código para alterar alguma coisa!

$conexao = conecta_bd();
$strQuery = "SELECT * FROM enquetes ORDER BY id DESC LIMIT 1";
$query = mysql_query($strQuery); // Se não houver uma enquete cadastrada, retorna a mensagem
if(mysql_num_rows($query) == 0){
echo "<br><br>Não há nenhuma enquete disponível no momento.";
}else{
$enquete = mysql_fetch_array($query);
if($_SESSION["_ja_votou"]){ // Aproveitando a mesma função... ;)
echo retornaResultadoEnquete($enquete["id"]);
}else{
$strQuery = "SELECT * FROM opcoes_enquetes WHERE enquetes_id=".$enquete["id"]." ORDER BY opcoes_ordem";
$query = mysql_query($strQuery); // Se não houver opções de resposta cadastrada, informa ao usuário (claro que você vai ser esperto e
// cadastrar respostas, afinal isso é uma enquete!... :) )

if(mysql_num_rows($query) == 0) {
echo "<br><br>Não há nenhuma enquete disponível no momento.";
}else{
echo "<br><strong><font face='verdana' size='1' color='#000000'> <b>".$enquete["enquete_titulo"]."</b></font></strong>";
// aqui estão os resultados encontrado no banco. Pergunta e respostas daquela pergunta.
while($opcao = mysql_fetch_array($query)) {
echo "<br><input type='radio' name='enquete_".$enquete["id"]."' value='".$opcao["opcoes_id"]."' id='opcao_".$opcao["opcoes_id"]."' onclick='document.getElementById(\"div_enquete\").innerHTML=\"Carregando, aguarde...\"; xajax_registraVoto(this.value,true,".$enquete["id"].",\"div_enquete\");'> <label for='opcao_".$opcao["opcoes_id"]."'> <font face='verdana' size='1' color='#000000'>".$opcao["opcoes_titulo"]."</font></label>";
}
}
}
}
?> </div>


Então o que obtivemos no código acima, é isto:

Entendendo o que aconteceu no arquivo enquetes.php

 require_once("includes/config.php");
Aqui, trazemos o arquivo de conexão ao banco, conforme abaixo: <?php
/* Arquivo de configurações
*
*/
define("DB_HOST","localhost");
define("DB_BANCO","minha base");
define("DB_USUARIO","usuario");
define("DB_SENHA","senha"); define("NOME_SESSAO","sessao_sistemas"); // Muda a codificação com a qual o XAJAX irá trabalhar define ('XAJAX_DEFAULT_CHAR_ENCODING', 'ISO-8859-1' );
?>

- require_once("includes/functions.php");
Este é o arquivo de funções utilizadas para apresentação da enquete, seleção das perguntas, respostas, e contagem dos votos após clicar na opção correspondente.
<?php
/* Arquivo de funções
*
*/
require_once("includes/config.php");
// Já deixo as bibliotecas do XAJAX disponíveis para toda a minha aplicação
require_once ("libs/xajax/xajax.inc.php"); /**
* Função que conecta ao banco de dados
*
*/

function conecta_bd()
{
$conexao = mysql_connect(DB_HOST,DB_USUARIO,DB_SENHA) or die(mysql_error()); mysql_select_db(DB_BANCO);
return $conexao;
} /**
* Função que grava um voto da enquete no banco de dados
*
*/

function registraVoto($id_opcao, $retorna_resultados=true, $id_enquete=false, $id_html="")
{
$conexao = conecta_bd(); $objResponse = new xajaxResponse(); // Para executar esse comando o usuário do MySQL precisa ter permissão de LOCK TABLES
mysql_query("LOCK TABLES enquetes READ, opcoes_enquetes WRITE"); // O intval é questão de segurança $strSQL = "UPDATE opcoes_enquetes SET opcoes_num_votos = opcoes_num_votos+1 WHERE opcoes_id=".intval($id_opcao);
mysql_query($strSQL); if($retorna_resultados)
$objResponse->addAssign($id_html,"innerHTML",retornaResultadoEnquete($id_enquete)); // Envia um alerta com o resultado da operação via AJAX
if(mysql_affected_rows() == 0)
$objResponse->addAlert("Houve erros durante o processamento do seu voto. Desculpe-nos o transtorno.");
else
{
$_SESSION["_ja_votou"] = true;
$objResponse->addAlert("Obrigado pela sua participação!");
} mysql_query("UNLOCK TABLES");
return $objResponse;
} /**
* Função que retorna os resultados de uma enquete em HTML
*
*/

function retornaResultadoEnquete($id_enquete)
{
$conexao = conecta_bd();
// Pega daos da enquete
$strSQL = "SELECT * FROM enquetes WHERE id=".intval($id_enquete);
$query = mysql_query($strSQL); if(mysql_num_rows($query) == 0)
return false;
else
{
$resultado = "";
$enquete = mysql_fetch_array($query);
$resultado .= "<font face='verdana' size='1' color='#000000'> <b>".$enquete["enquete_titulo"]."</b></font>"; // Conta o total de votos
$strQuery = "SELECT SUM(opcoes_num_votos) AS 'total_votos' FROM opcoes_enquetes WHERE enquetes_id=".$enquete["id"];
$query = mysql_query($strQuery);
$row = mysql_fetch_array($query);
$total_votos = $row["total_votos"]; // Pega opções de resposta
$strQuery = "SELECT * FROM opcoes_enquetes WHERE enquetes_id=".$enquete["id"]." ORDER BY opcoes_num_votos DESC";
$query = mysql_query($strQuery);
// monta a tabelinha com a estatística de perguntas respondidas, por porcentagem de votos.
$resultado .= "<table border='0'>";
while($opcao = mysql_fetch_array($query))
{
$resultado .= "<tr><td><font face='verdana' size='1' color='#000000'>" .$opcao["opcoes_titulo"]."</td> <td align='right'><font face='verdana' size='1' color='#000000'>".number_format((($opcao["opcoes_num_votos"] /$total_votos)*100),1,",",".")."% - ".$opcao[opcoes_num_votos]." votos</font></td></tr>";
}
$resultado .="<tr><td><br><font face='verdana' size='1' color='#000000'><b> Total de votos recebidos: $total_votos</b></font></td></tr>";
$resultado .= "</table>";
} return $resultado;
}
?>

Por fim, o trecho:

<?php
// Comandos AJAX (olhe, mas não mexa... :) )
require("ajax/enquete.common.php");
// Imprime os códigos javscript da classe Xajax para a página
$xajax->printJavascript("libs/xajax/");
?>


Pede os arquivos da classe XAJAX, que você pode estudar a adaptar para outros usos, pois ela é bastante completa, e bem documentada. Visite o site do projeto XAJAX e conheça mais sobre esta classe.

Finalizando:
Votei em uma opção. Automaticamente o voto será computado (através do arquivo functions.php) e gravado no banco.
Será então exibida a tela com os votos computados, por ordem do mais votado.

E no banco, agora você pode ver, que foi computado um voto na 4ª opção de resposta:

Espero que este artigo tenha-lhe sido útil, e para seus posteriores estudos, CLIQUE AQUI e faça o download dos arquivos utilizados!
Você também pode ver o demo do sistema em funcionamento, aqui: http://www.flaviajobs.com.br/sistemas/enquete_ajax/enquete.php

Comentários, dúvidas ou sugestões, me escrevam.
fjferr@gmail.com

Opções de Interação

Comentários

ERRO
Por: Gleyston, 04/03/2010   17:07:30
Olá. Bom está dando o seguinte erro:

Warning: mysql_select_db(): supplied argument is not a valid MySQL-Link resource in /home/mestre/public_html/novo-site/enquete/adm.php on line 37

Warning: mysql_query(): supplied argument is not a valid MySQL-Link resource in /home/mestre/public_html/novo-site/enquete/adm.php on line 38

O que será que está acontecendo? Já tentei de várias formas aqui e não consegui. Poderia me dar uma ajuda? Obrigado.
Essa Classe onde tem?
Por: Jose, 26/03/2009   10:20:15
"../../Connections/testes.php"
Não veio junto dos arquivos