> Manuales > Trabajo con Ajax en PHP utilizando Xajax

Pasamos a mejorar el sistema de votación con xajax dado en el artículo anterior.

Para empezar tenemos que recordar que para este ejemplo ya creamos un formulario de votación, que va a ser el mismo y una función que realizaba las acciones necesarias, así como una tabla en la base de datos. Para los que se incorporan nuevos a este artículos os recomiendo que leáis el articulo de Sistema de votación con xajax para que puedan entender este ya que no vamos a repetir los pasos nuevamente.

Esta vez vamos a comprobar si el que vota ya ha votado anteriormente, para ello utilizaremos las ips, por lo que tenemos que crear otra tabla en nuestra base de datos.

La tabla la vamos a llamar articulo_ip y va a tener el siguiente aspecto:


Una vez que tenemos la tabla vamos a modificar la función que tenemos creada llamada votar. Los primero es crear unas variables de configuración al inicio de la función.

//CONFIGURACION
   $tabla_control='articulo_ip';//tabla que controla las ip de las votaciones
   $identificador='id_articulo';//nombre del campo en la tabla que controle las votaciones
   $tabla_votos='articulo_voto';//tabla con el log de los votos
   $id_cookie='rating_articulo';
   $dias_votar_misma_ip = 2;


Después tenemos que crearnos una función que nos devuelva la ip real del visitante para ello utilizaremos esta función que ya tenemos construida y comentada.

function getRealIP()
{

if( $_SERVER['HTTP_X_FORWARDED_FOR'] != '' )
{
$client_ip =
( !empty($_SERVER['REMOTE_ADDR']) ) ?
$_SERVER['REMOTE_ADDR']
:
( ( !empty($_ENV['REMOTE_ADDR']) ) ?
$_ENV['REMOTE_ADDR']
:
"unknown" );

// los proxys van añadiendo al final de esta cabecera
// las direcciones ip que van "ocultando". Para localizar la ip real
// del usuario se comienza a mirar por el principio hasta encontrar
// una dirección ip que no sea del rango privado. En caso de no
// encontrarse ninguna se toma como valor el REMOTE_ADDR

$entries = split('[, ]', $_SERVER['HTTP_X_FORWARDED_FOR']);

reset($entries);
while (list(, $entry) = each($entries))
{
$entry = trim($entry);
if ( preg_match("/^([0-9]+.[0-9]+.[0-9]+.[0-9]+)/", $entry, $ip_list) )
{
// http://www.faqs.org/rfcs/rfc1918.html
$private_ip = array(
'/^0./',
'/^127.0.0.1/',
'/^192.168..*/',
'/^172.((1[6-9])|(2[0-9])|(3[0-1]))..*/',
'/^10..*/');

$found_ip = preg_replace($private_ip, $client_ip, $ip_list[1]);

if ($client_ip != $found_ip)
{
$client_ip = $found_ip;
break;
}
}
}
}
else
{
$client_ip =
( !empty($_SERVER['REMOTE_ADDR']) ) ?
$_SERVER['REMOTE_ADDR']
:
( ( !empty($_ENV['REMOTE_ADDR']) ) ?
$_ENV['REMOTE_ADDR']
:
"unknown" );
}
return $client_ip;
}


Una vez que tenemos la función la añadimos a nuestro archivo antes de la función de votar para así poder trabajar con ella y pasamos a modificar la función votar comprobando si hay cookies creadas o si tenemos la ip del usuario en nuestra tabla almacenada. Para ello creamos el siguiente código.

//controlamos que vote una sola vez
      //controlamos si hay una cookie que impida la votacion
      $nombre_cookie=$id_cookie.'_'.$id_articulo;
      if ($_COOKIE[$nombre_cookie]){
         //si hay cookie no permitimos la votacion
         $res="Ya has votado";
         //return $salida = false;
      }else{//si no hay cookie
         //miramos si muestra ip
         $ip=getRealIP();
   
         if(!$ip){
            $res= "Incapaz de contabilizar";
            //return $salida = false;//si no la muestra la ip, no permitimos el voto
         }else{
            $segundos_votar_misma_ip = 86400 * $dias_votar_misma_ip;
            
            //borramos los registros de los dias de antiguedad que deseamos
            $ssql= "delete from articulo_ip where fecha+$segundos_votar_misma_ip < unix_timestamp()";
            $rs = mysql_query($ssql);
            
            //miramos si esta IP ya ha votado este recurso ultimamente (1 dia)
            $ssql = "select * from articulo_ip where (id_articulo=$id_articulo and ip = '$ip' and unix_timestamp()-fecha<$segundos_votar_misma_ip)";
            //echo $ssql;
            $rs = mysql_query($ssql);
            
            //si no ha votado lo incorporamos en la tabla de control y creamos el voto
            if (mysql_num_rows($rs) == 0) {
               //metemos la ip en la tabla de control de voto
               $ssql = "insert into articulo_ip (id_articulo, ip, fecha) values ($id_articulo, '$ip', unix_timestamp())";
               mysql_query($ssql);
               
               //insertamos el voto
               $ssql= "insert into articulo_voto (votacion, id_articulo, ) values ($votacion, $id_breve)";
               //echo $ssql;
               mysql_query($ssql);
               mysql_free_result($rs);
               
               //colocamos una cookie
               //setcookie($nombre_cookie, time(), time() + $segundos_votar_misma_ip);
               $res="Gracias por tu voto";
               //return true;
            }else{
               $res="Ya has votado";
               //return false;
            }
         }


Este código esta explicado para que vayáis viendo que hemos en cada momento pero básicamente lo que hace es, primero comprueba que no haya ninguna cookie, si no la hay pues pasa a comprobar si hay algún registro en la tabla de ips, y si no lo hay inserta el voto, sino nos muestra un mensaje de que ya ha votado.

Nota: Este script se ha creado con la sintaxis de la versión 0.2.5 de Xajax. Para hacerlo funcionar si trabajáis con la nueva versión 0.5 de Xajax, leer las notas: Actualiza tu framework y los scripts a Xajax 0.5.

A continuación pongo el código completo de la función para que os quede del todo claro.

<?
require ($raiz . '../../../xajax/xajax.inc.php');

//instanciamos el objeto de la clase xajax
$xajax = new xajax();
$xajax->setCharEncoding('ISO-8859-1');
$xajax->decodeUTF8InputOn();
//conecto con la base de datos
$conn = mysql_connect("servidor","usuario","contraseña");
//selecciono la BBDD
mysql_select_db("base de datos",$conn);
//////////////////////////////////////////////////////////////////////////////////////////////////
//OBTIENE Y DEVUELVE LA IP REAL DE UN VISITANTE
//////////////////////////////////////////////////////////////////////////////////////////////////
function getRealIP()
{

if( $_SERVER['HTTP_X_FORWARDED_FOR'] != '' )
{
$client_ip =
( !empty($_SERVER['REMOTE_ADDR']) ) ?
$_SERVER['REMOTE_ADDR']
:
( ( !empty($_ENV['REMOTE_ADDR']) ) ?
$_ENV['REMOTE_ADDR']
:
"unknown" );

// los proxys van añadiendo al final de esta cabecera
// las direcciones ip que van "ocultando". Para localizar la ip real
// del usuario se comienza a mirar por el principio hasta encontrar
// una dirección ip que no sea del rango privado. En caso de no
// encontrarse ninguna se toma como valor el REMOTE_ADDR

$entries = split('[, ]', $_SERVER['HTTP_X_FORWARDED_FOR']);

reset($entries);
while (list(, $entry) = each($entries))
{
$entry = trim($entry);
if ( preg_match("/^([0-9]+.[0-9]+.[0-9]+.[0-9]+)/", $entry, $ip_list) )
{
// http://www.faqs.org/rfcs/rfc1918.html
$private_ip = array(
'/^0./',
'/^127.0.0.1/',
'/^192.168..*/',
'/^172.((1[6-9])|(2[0-9])|(3[0-1]))..*/',
'/^10..*/');

$found_ip = preg_replace($private_ip, $client_ip, $ip_list[1]);

if ($client_ip != $found_ip)
{
$client_ip = $found_ip;
break;
}
}
}
}
else
{
$client_ip =
( !empty($_SERVER['REMOTE_ADDR']) ) ?
$_SERVER['REMOTE_ADDR']
:
( ( !empty($_ENV['REMOTE_ADDR']) ) ?
$_ENV['REMOTE_ADDR']
:
"unknown" );
}
return $client_ip;
}
function votar($id_articulo, $votacion){
   global $raiz;
   $respuesta = new xajaxResponse('ISO-8859-1');
   //echo "prueba";      
   //CONFIGURACION
   $tabla_control='articulo_ip';//tabla que controla las ip de las votaciones
   $identificador='id_articulo';//nombre del campo en la tabla que controle las votaciones
   $tabla_votos='articulo_voto';//tabla con el log de los votos
   $id_cookie='rating_articulo';
   $dias_votar_misma_ip = 2;

      //controlamos que vote una sola vez
      //controlamos si hay una cookie que impida la votacion
      $nombre_cookie=$id_cookie.'_'.$id_articulo;
      if ($_COOKIE[$nombre_cookie]){
         //si hay cookie no permitimos la votacion
         $res="Ya has votado";
         //return $salida = false;
      }else{//si no hay cookie
         //miramos si muestra ip
         $ip=getRealIP();
   
         if(!$ip){
            $res= "Incapaz de contabilizar";
            //return $salida = false;//si no la muestra la ip, no permitimos el voto
         }else{
            $segundos_votar_misma_ip = 86400 * $dias_votar_misma_ip;
            
            //borramos los registros de los dias de antiguedad que deseamos
            $ssql= "delete from articulo_ip where fecha+$segundos_votar_misma_ip < unix_timestamp()";
            $rs = mysql_query($ssql);
            
            //miramos si esta IP ya ha votado este recurso ultimamente (1 dia)
            $ssql = "select * from articulo_ip where (id_articulo=$id_articulo and ip = '$ip' and unix_timestamp()-fecha<$segundos_votar_misma_ip)";
            //echo $ssql;
            $rs = mysql_query($ssql);
            
            //si no ha votado lo incorporamos en la tabla de control y creamos el voto
            if (mysql_num_rows($rs) == 0) {
               //metemos la ip en la tabla de control de voto
               $ssql = "insert into articulo_ip (id_articulo, ip, fecha) values ($id_articulo, '$ip', unix_timestamp())";
               mysql_query($ssql);
               
               //insertamos el voto
               $ssql= "insert into articulo_voto (votacion, id_articulo, ) values ($votacion, $id_breve)";
               //echo $ssql;
               mysql_query($ssql);
               mysql_free_result($rs);
               
               //colocamos una cookie
               //setcookie($nombre_cookie, time(), time() + $segundos_votar_misma_ip);
               $res="Gracias por tu voto";
               //return true;
            }else{
               $res="Ya has votado";
               //return false;
            }
         }
      }      
   
   //Saco el número de votos de este articulo
   $ssql_voto="select count(id_voto) as 'cuantos' from articulo_voto where id_articulo=$id_articulo";
   $rs_voto=mysql_query($ssql_voto);
   $fila_voto=mysql_fetch_object($rs_voto);

   $act="<b>Número de votos</b>:".$fila_voto->cuantos."<br>";

   //saco la votacion media del articulo
   $ssql_media="select avg(votacion) as media from articulo_voto where id_articulo=".$id_articulo;
   $rs_media=mysql_query($ssql_media);
   $fila_media=mysql_fetch_object($rs_media);
   $act .="<b>Votación media</b>: <br>";
   if (!is_null($fila_media->media)){
      $absoluto=intval($fila_media->media);
      $decimal=$fila_media->media-$absoluto;
         if($absoluto>0){
         for ($x = 1; $x <= $absoluto; $x++){
            $act .='<img src="../../../images/estrella.gif" width=14 height=13>';
         }
         if($decimal>=0.5){
            $act .='<img src="../../../images/estrellamitad.gif" width=14 height=13>';
         }
      }
   }else{
      $act .= "<i>Nadie ha votado por este artículo</i>";
   }
   $act .="<br>";
   
   
   $respuesta->addAssign("votar_articulo","innerHTML",$res);
   $respuesta->addAssign("actualizar","innerHTML",$act);
   return $respuesta;
}

//asociamos la función creada anteriormente al objeto xajax
$xajax->registerFunction("votar");
//El objeto xajax tiene que procesar cualquier petición
$xajax->processRequests();
$xajax->printJavascript("../../../xajax/");
?>
<script>
function votar_articulo(id_articulo){

         var puntos = document.votar.puntos.value;
         xajax_votar(id_articulo,puntos)
                  
   }


</script>


<div style="width:192px;font-size:12pt; margin-top:3px;">
<div ><b>Participa:</b></div>
<table cellspacing="2" cellpadding="2" border="0" width="190">
<tr>
<td width="130" align=center class=fuente8>
   <div id="votar_articulo">
   <?
   /*if ($respuesta!="")
      echo " <i>$respuesta</i> <br> ";*/
   //muestra_media_votos_pagina($id_breve);
   ?>
   

Puntua el artículo:
<br>
<form action="sistema_votacion.php" method="post" name=votar style="margin:0px;">
<select name="puntos">
<option value=1>1
<option value=2>2
<option value=3>3
<option value=4>4
<option value=5>5
</select>
<input type='button' name='votar' value='Votar' onClick='votar_articulo(1)'>
</form>

</div>
   </div>
   </td>
</tr>
<tr><td class=fuente8 align=center><div id=actualizar></div></td></tr>
</table>


</div>


Para finalizar os dejamos un enlace a un ejemplo funcionando.

Sara Alvarez

Equipo DesarrolloWeb.com

Manual