Tuesday, 26 August 2008

En PHP recuperar el ultimo ID de un INSERT MySQL

Programando en PHP, ¿alguna vez has necesitado saber el valor generado para un ID autoincremental después de una consulta tipo INSERT? ¿eres de los que -como yo- se ha complicado la vida haciendo una consulta SELECT para encontrar el id más alto en esa tabla o el max(ID)? Pues anota la siguiente instrucción ;)

Te pondré un simple ejemplo de 3 líneas, y verás qué sencillo: supongamos que tienes una tabla llamada 'mi_tabla1' que tiene un campo ID de tipo AUTO_INCREMENT, y necesitas insertar un registro y luego saber inmediatamente cuál es el ID que se ha generado para él, con tal de poder aprovecharlo en otras tablas.

Veamos esas 3 líneas de código:

mysql_query("INSERT mi_tabla1 SET `mi_campo`='mi_valor'");
$ultimo_ID = mysql_insert_id();
mysql_query("INSERT mi_tabla2 SET `id1`='".$ultimo_ID."'");


Breve explicación: en la primera línea insertamos un nuevo registro en la tabla 'mi_tabla1'. En la segunda línea recuperamos CON UNA SOLA INSTRUCCIÓN el último valor "autogenerado" (tiene que haber un campo AUTO_INCREMENT en esa tabla) por la última inserción realizada en la conexión MySQL establecida por el script en ejecución. En la tercera línea utilizamos ese valor para añadir un nuevo registro con ese ID asociado a un campo que esta vez no será AUTO_INCREMENT, pero que permitirá relacionar los registros de ambas tablas.

Cómo habréis notado, el quit de la cuestión está en la función de PHP mysql_insert_id().

Tuesday, 19 February 2008

Cómo evitar que los buscadores indexen nuestras páginas seguras

¿Has incluido páginas SSL seguras en tu sitio web, y los buscadores han empezado a indexarte de nuevo todas tus páginas HTTP como HTTPS, cual duplicados? ¿Sabías que curiosamente eso puede penalizar la posición de tu web en los rankings de esos mismos buscadores?

Como este era mi caso, estuve buscando información para solucionarlo, y aquí os he traducido del inglés un articulo que detalla dos soluciones. El original podéis leerlo en www.seoworkers.com.


Muchos sitios web tienen páginas que utilizan SSL. Esto permite que el intercambio de información entre el servidor y el navegador del visitante suceda en una conexión encriptada, para garantizar la provacidad y la integridad de la misma.

Las URLs (direcciones) de páginas encriptadas con SSL comienzan con https en lugar de con http, para indicar que trabajan sobre un protocolo seguro.

El caso es que si las páginas seguras de tu sitio web han sido indexadas por los buscadores juntamente con el resto de páginas estandar, puedes experimentar serios problemas de canonicalización.


[NT: por ejemplo, que los buscadores consideren que tu página principal sea https://www.midominio.com antes que http://www.midominio.com -tal vez no conteniendo la misma información!!! O también -aún peor- puede que los buscadores interpreten que estás intentando "duplicar" el contenido de tu web con modos fraudulentos, y pueden penalizarte por ello!!! En cualquier caso, es perjudicial para la adecuada presencia de tu web en los buscadores.]

Estos problemas aparecen solo si tienes las páginas seguras dentro del mismo subdominio en el que tienes las páginas estandar.

En cambio, en el caso de que tus páginas seguras las tengas bajo un subdominio exclusivo [NT, por ejemplo: https://pagos.midominio.com] puedes fácilmente excluirlas de la indexación usando el archivo robots.txt en la raíz del directorio de ese subdominio.

En algunos casos solamente una página requiere el uso de SSL (como el formulario de contacto o de pagar). La opción más cómoda y habitual en esos casos es tener esa página siguiendo la estructura estandar del resto del sitio web. Cambiando solamente el "prefijo de protocolo" de la dirección de esa página (de http a https).


Sin embargo, esta técnica es la que nos puede llevar a los problemas de indexación en los buscadores que antes hemos comentado, puesto que los buscadores, si siguen los enlaces que salgan de esa única página SSL, son llevados a "duplicados" de las páginas estandar del sitio, pero con el prefijo https [NT: hay que recalcar aquí que para los buscadores la dirección http://www.midominio.com/servicios.htm es en principio diferente que https://www.midominio.com/servicios.htm, con lo cuál indexará las dos direcciones como páginas diferentes].

Esto sucede porque normalmente todos los enlaces internos dentro de un sitio web son enlaces relativos y por tanto heredan el protocolo y el dominio de la página en donde aparecen.En conclusión, Google -y posiblemente los otros buscadores- pueden considerar esta situación como un intento de "duplicación" de contenidos [NT: técnica que algunos desarrolladores de webs intentan de vez en cuando para engañar a los buscadores, y que por tanto está muy penalizado]. Y esto se traduciría en que los buscadores que quisiseran penalizarte rebajarían la posición de tu página en el ranking páginas en las búsquedas de los internautas.

Una vez indexadas, Google continuará visitando esas páginas seguras de tu sitio, a menos que las excluyas mediante el archivo robots.txt o con meta tags [NT: meta etiquetas] especiales en la cabecera de cada página.


Entonces, ¿cómo puedo evitar que Google visite esas páginas?

Si te encuentras en la posición descrita, te parecerá que no hay manera de solucionarlo fácilmente.

Hay una manera de que el archivo robots.txt redireccione las peticiones de páginas seguras a un segundo archivo que excluiría las páginas seguras a los programas de rastreo.

Para aplicar esta solución, sin embargo, debes usar el servidor Apache en tu hosting con el mod_rewrite activado [NT en inglés "enabled"].

Primero, deberías crear un segundo archivo robots.txt, llamándolo robots_ssl.txt (o el nombre que prefieras), asegurándote de que bloquea a los rastreadores de todos los buscadores. Súbelo a la raíz de tu dominio.

Para más información acerca del archivo robots.txt, qué es y cómo funciona, visita The web Robots Pages [NT: en habla hispana es recomendable WebRecursos - robots.txt].

Aquí tienes un ejemplo de este archivo:


User-agent: Googlebot
Disallow: /

User-agent: *
Disallow: /


Además, necesitarás añadir los siguientes comandos al archivo .htaccess que haya en la raíz de archivos de tu servidor [NT: root document folder]:

RewriteEngine on
Options +FollowSymlinks
RewriteCond %{SERVER_PORT} ^443$
RewriteRule ^robots.txt$ robots_ssl.txt

Resumidamente, este comando ordena al servidor web a dirigir cualquier petición para el archivo robots.txt que provenga del puerto 443 (usado para las conexiones SSL, en lugar del puerto 80 habitual para las conexiones web estandar) al segundo archivo que creamos, y que bloquea la indexación.

Para poder comprobar que está funcionando esta técnica, escribe la URL de tu archivo robots.txt en tu navegador para ver el comportamiento habitual del mismo para comandos estandar. Y luego prueba a escribir la misma URL pero con el prefijo de protocolo seguro (https) y deberías ver el contenido del segundo archivo, robots_ssl.txt.

¿Qué puedo hacer si no puedo utilizar mod_rewrite?

Si te es imposible activar mod_rewrite, ya sea porque no utilizas un servidor Apache, o porque no está habilitada esta función, todo lo anterior no te sirve de nada.

Si utilizas PHP para generar las páginas de tu site, puedes utilizarlo para comprobar si se está llamando a tu página mediante SSL, y en caso afirmativo puedes incluir un meta tag en la cabecera [NT: head] de tus documentos para desactivar la indexación por los buscadores.

El siguiente código, situado en cualquier parte de la cabecera de tu documento [NT: entre <head> y </head>] insertará el meta tag robots si el valor de la variable HTTPS del servidor está establecida a 'on':

1  <?php
2  
3       
if (isset($_SERVER['HTTPS']) 
4                 && 
strtolower($_SERVER['HTTPS'])=='on'){
5  
6       echo 
"\n<meta name='robots' content='noindex,nofollow'>";
7  
8       }
9  
10  
?>
Para verificar el funcionamiento correcto de este código, visita cualquier página en la que lo hayas incluido utilizando SSL (https://www.midominio.com/archivo.php). Y luego usa el comando ver codigo fuente de tu navegador para comprobar que el metatag aparece insertado en la cabecera del documento.


Enlaces de interés


Friday, 9 November 2007

JSON, contenidos dinamicos en tu web

¿Has intentado utilizar AJAX pero te parece muy complicado o tal vez sus librerías las encuentras muy pesadas de cargar? JSON es su hermano pequeño, y aunque es anterior en el tiempo es más que suficiente para la mayoría de aplicaciones web y es mucho más sencillo de utilizar. Veamos un sencillo pero operativo ejemplo a continuación, que tú podrás cambiar a tu medida, y además por lo que he probado funciona perfectamente en IE (Internet Explorer 6) y en FF (FireFox 2).

No ha sido una tarea fácil conseguir que este código funcionara. Me he pasado horas y horas buscando documentación oficial de los objetos utilizados, he consultado en foros, etc... y por fin, después de copiar y pegar de aquí y de allá, parece que el esfuerzo se concretó en algo operativo y multiplataforma ;)

Nuestro ejemplo consta de 4 archivos:

  • index.htm. Es el documento HTML que verá el visitante en el navegador y el que irá haciendo las llamadas al servidor SIN NECESIDAD DE RECARGARSE LA PÁGINA.
  • json_1.php. Es el archivo PHP al que llamará index.htm cuando necesite nuevos datos.
  • funciones.php. Contiene dos funciones en PHP necesarias para preparar los datos que quiera enviar json_1.php a index.htm.
  • smile.gif. Es una imagen que utilizaremos de ejemplo, para comprobar que con JSON podemos trabajar dinámicamente en nuestras aplicaciones web con texto y con imágenes.
Antes de mostraros el código, deciros que como veréis, es muy claro qué debéis adaptar a vuestro caso, y que las posibilidades son ilimitadas utilizando estas pocas funciones. Lo que más problemas me dió fue -como sucede a menudo- que funcionase todo bien en IE y en FF. Cuando me iba en uno no me iba en el otro... en fin... parece que ahora ya sí. Bueno, al menos hasta que alguno de esos dos navegadores vuelva a cambiar ("mutar" ?).

Para hacer funcionar el ejemplo, debéis poner los 4 archivos en una misma carpeta de vuestro servidor y desde un navegador llamar al archivo index.htm. Así de sencillo. Ah, y bueno, para que lo tengáis más fácil, os dejo este enlace para que podáis descargaros un RAR con el ejemplo listo para probar ;)

También podéis ver el ejemplo funcionando. No os podéis quejar :)

index.htm
1  <html>
2  <head>
3       <title>.: JSON - ejemplo sencillo :.</title>
4       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
5  </head>
6  
7  <body>
8  
9  <a href="javascript:remote_fill('json_1.php?color=rojo');">ROJO</a>
10  <a href="javascript:remote_fill('json_1.php?color=azul');">AZUL</a>
11  <br /><br /><br />
12  <span id='json_grafico'></span>
13  <span id='json_texto'></span>
14  
15  <script>
16  
17  // INTENTAR LA CREACION DE UNA CONEXION DIRECTA CON EL SERVIDOR MEDIANTE XMLHttpRequest
18  
19  function createRequest() {
20       try {
21            request = new XMLHttpRequest();
22       } catch (trymicrosoft) {
23            try {
24                 request = new ActiveXObject('Msxml2.XMLHTTP');
25            } catch (othermicrosoft) {
26                 try {
27                      request = new ActiveXObject('Microsoft.XMLHTTP');
28                 } catch (failed) {
29                      request = false;
30                 }
31            }
32       }
33       if (!request)
34       alert('Su navegador no permite crear uns instancia de XMLHttpRequest, ni de Msxml2.XMLHTTP, ni de Microsoft.XMLHTTP. Esta característica es indispensable para seguir trabajando en esta aplicación web.');
35  }
36  
37  var request = false;
38  createRequest();
39  
40  // FUNCIONES DE TRABAJO CON EL SERVIDOR
41  
42  function remote_fill(url_remote){
43       request = false;
44       createRequest();
45       if (!request){
46            alert('Su navegador no permite crear uns instancia de XMLHttpRequest, ni de Msxml2.XMLHTTP, ni de Microsoft.XMLHTTP. Esta característica es indispensable para seguir trabajando en esta aplicación web.');
47            return false;
48       }
49       request.onreadystatechange = handle_json;
50       request.open('GET', url_remote, true);
51       request.send(null);
52  }
53  
54  function handle_json() {
55       if (request.readyState == 4) {
56            if (request.status == 200) {
57                 var json_data = request.responseText;
58                 var the_object = eval( '(' + json_data + ')' );
59                 document.getElementById('json_grafico').innerHTML= the_object.grafico_pertinente;
60                 document.getElementById('json_texto').innerHTML= the_object.texto_pertinente;
61            } else {
62                 alert('Ha habido un problema con la URL ');
63            }
64       }
65  }
66  
67  remote_fill('json_1.php?color=blanco');
68  
69  </script>
70  
71  </body>
72  </html>


json_1.php
1  <?php
2       
if (!isset($_GET['color'])) return false;
3       include_once(
"funciones.php");
4       
5       
$ret = array();
6       switch (
$_GET['color']){
7            case 
"rojo":
8                 
$ret['grafico_pertinente'] = "<img src='smile.gif' style='border:1px #ff0000 solid' />";
9                 
$ret['texto_pertinente'] = " borde rojo";
10                 break;
11            case 
"azul":
12                 
$ret['grafico_pertinente'] = "<img src='smile.gif' style='border:1px #0000ff solid' />";
13                 
$ret['texto_pertinente'] = " borde azul";
14                 break;
15            default:
16                 
$ret['grafico_pertinente'] = "<img src='smile.gif' style='border:0px #ff0000 solid' />";
17                 
$ret['texto_pertinente'] = " escoge un color para el borde, y el servidor devolverá la respuesta";
18                 break;
19       }
20       
21       echo 
php_json_encode($ret);
22  
23  
?>


funciones.php
1  <?php
2  
3  
// funciones JSON
4  
function json_encode_string($in_str){
5       
//$charset = "UTF-8";
6       
$charset "ISO-8859-1";
7       
mb_internal_encoding($charset);
8       
$convmap = array(0x800xFFFF00xFFFF);
9       
$str "";
10       for(
$i=mb_strlen($in_str)-1$i>=0$i--){
11            
$mb_char mb_substr($in_str$i1);
12            if(
mb_ereg("&#(\\d+);"mb_encode_numericentity($mb_char$convmap$charset), $match))
13                 
$str sprintf("\\u%04x"$match[1]) . $str;
14            else
15                 
$str $mb_char $str;
16       }
17       return 
$str;
18  }
19  
20  function 
php_json_encode($arr){
21       
$json_str "";
22       if(
is_array($arr)){
23            
$pure_array true;
24            
$array_length count($arr);
25            for(
$i=0;$i<$array_length;$i++){
26                 if(! isset(
$arr[$i])){
27                      
$pure_array false;
28                      break;
29                 }
30            }
31            if(
$pure_array){
32                 
$json_str ="[";
33                 
$temp = array();
34                 for(
$i=0;$i<$array_length;$i++)
35                 
$temp[] = sprintf("%s"php_json_encode($arr[$i]));
36                 
$json_str .= implode(",",$temp);
37                 
$json_str .="]";
38            }else{
39                 
$json_str ="{";
40                 
$temp = array();
41                 foreach(
$arr as $key => $value)
42                 
$temp[] = sprintf("\"%s\":%s"$keyphp_json_encode($value));
43                 
$json_str .= implode(",",$temp);
44                 
$json_str .="}";
45            }
46       }else{
47            if(
is_string($arr)){
48                 
$json_str "\""json_encode_string($arr) . "\"";
49            }elseif(
is_numeric($arr)){
50                 
$json_str $arr;
51            }else{
52                 
$json_str "\""json_encode_string($arr) . "\"";
53            }
54       }
55       return 
$json_str;
56  }
57  
58  
?>