jueves, 24 de mayo de 2012

CSS clearfix

A la hora de maquetar, uno de los problemas clásicos que nos encontramos son las capas que contienen elementos flotados, y que no los cubren en su totalidad.

La solución "antigua" consistía en añadir un elemento al final con un "clear: both;", para obligar que la capa externa contenga todos los elementos.

Posteriormente, se han usado otros artificios, como el típico estilo "clearfix".

Sin embargo, nuestro compañero Javier Asuar nos comenta que parece que hay una solución más sencilla. Bastaría con añadir un "overflow: hidden;" a la capa contenedora. Ojo, que en algunos casos debemos añadir un "min-width", para asegurarnos de que las barras de scroll aparecen si el tamaño de la ventana es demasiado pequeño.

Enlaces de referencia:

Jugando con expresiones regulares en PHP

Gracias a nuestro compañero Armando Antón, tenemos aquí un pequeño ejemplo sobre el uso de expresiones regulares en PHP. Para los que estamos trabajando continuamente con HTML nos suelen venir muy bien a la hora de reemplazar contenidos.

En este caso nos centramos en los modificadores que permiten procesar cadenas de varias líneas, de forma "avariciosa" (greedy) o "perezosa" (lazy o non-greedy).

viernes, 11 de noviembre de 2011

MySQL: Devolver los resultados según un orden establecido

Básicamente, la mayoría de consultas que hacemos a la base de datos constan de tres aspectos: de dónde queremos obtener los datos, con qué criterios queremos seleccionar los datos y en qué orden los necesitamos. Nos vamos a centrar en este último aspecto.

Normalmente nos basta con ordenar los resultados por orden numérico, antigüedad o alfabéticamente. Pero, a veces, necesitaremos que se devuelvan en un orden predeterminado.

Para ello, podemos echar mano de la función de MySQL FIND_IN_SET(). Dicha función devuelve la posición de una cadena dentro de una lista de elementos separados por comas. Por ejemplo:

FIND_IN_SET('jueves', 'lunes,martes,miércoles,jueves,viernes,sábado,domingo') => 4

Si la cadena no se encuentra, la función devuelve 0.

Es importante, si no os queréis romper la cabeza preguntándoos por qué no funciona, que no haya espacios en blanco entre las comas.

Fuente: FIND_IN_SET() :: MySQL Function of the Day

jueves, 14 de julio de 2011

Parsear ficheros XML grandes

Cuando tenemos que integrarnos con servicios de terceros, lo más normal es que intercambiemos la información en formato XML o JSON (esto se está poniendo de moda últimamente). Con PHP4, parsear XML es poco menos que un suplicio, pero con PHP5 la cosa cambia.
Disponemos de la extensión SimpleXML que, de forma muy sencilla, nos permite indicar un XML de entrada y lo tendremos cargado en un bonito y accesible objeto.
Sin embargo, esta solución no es viable cuando vamos a procesar XML de gran tamaño, ya que estaríamos cargando toda la información en memoria. Normalmente no será necesario, ya que lo que se suele hacer es recorrer el XML buscando alguna información concreta, o bien convertirlo a otro formato o cargarlo en nuestra base de datos.
Para este tipo de operaciones es mejor usar la extensión XMLReader. Su funcionamiento es parecido al de un cursor que va recorriendo el XML. Por tanto, al no parsearlo entero, el consumo de memoria es mucho menor.
Vistas estas dos alternativas (hay algunas más), a la hora de procesar un XML entero una buena solución puede ser combinar ambos métodos. Es decir, usar XMLReader para ir recorriendo los nodos e ir cargando cada uno de ellos con SimpleXML, para que el manejo de la información contenida sea trivial.
Sería algo así:
Fuente: http://stackoverflow.com/questions/1835177/how-to-use-xmlreader-in-php

viernes, 8 de julio de 2011

Códigos de países, provincias y ciudades

Buscando información sobre listados de localidades me he encontrado este post de Carme Pla en el que parece estar trabajando en algo parecido y comparte su experiencia.
Los ficheros que encuentro más interesantes son:
Pero, sin duda, el gran descubrimento ha sido la web GeoNames, en la que podemos encontrar listados de prácticamente todas las localidades del mundo, y con licencia Creative Commons. Desde luego un gran trabajo que se merece una donación.
Sobre todo, es importante usar códigos más o menos estandarizados, porque siempre nos será más fácil integrarnos con servicios que empleen la misma estandarización y nos ahorraremos pasos de traducción de identificadores. Si no fuera así, mi recomendación es usar siempre un sistema de identificadores interno, que se ajuste a nuestro modelo de datos y que no dependa de ningún proveedor (porque luego lo cambias por otro y te quedas con el "culo al aire" y mucho código que cambiar).

jueves, 16 de junio de 2011

Cómo integrar reCAPTCHA en Wordpress

Últimamente estamos recibiendo mucho spam en los blogs de la plataforma. Y eso que tenemos instalado un plugin, WP-SpamFree, que parece que no está realizando del todo bien su trabajo.

Así que como primera medida preventiva, vamos a introducir un captcha en el formulario de envío de comentarios. La más popular de estas herramientas, adquirida y auspiciada hace tiempo por Google, es reCAPTCHA.

Supuestamente hay disponible un plugin para Wordpress. Y digo supuestamente porque el plugin parece haberse roto en las versiones 3.x de WP. Así que nuestro gozo en un pozo.

Tenemos, pues, tres opciones:

  • Buscar otro plugin que permita añadir captchas a los formularios. La verdad es que no nos ha convencido ninguno.
  • Arreglar el plugin de reCAPTCHA. Como contribución a la comunidad estaría genial, pero no tenemos los conocimientos ni la experiencia suficientes como para afrontar la tarea en un corto periodo de tiempo.
  • Modificar nosotros el código de nuestro tema de Wordpress para añadir reCAPTCHA.

Al final hemos optado por la última opción. Una vez efectuadas las investigaciones pertinentes, no ha resultado demasiado complicado.

La implementación en el formulario es muy sencilla, siguiendo las instrucciones que podemos encontrar en su web: http://code.google.com/apis/recaptcha/docs/display.html.

Ahora sólo queda comprobar, a la hora de procesar el alta de comentarios, que el captcha introducido es correcto. Para ello, nuevamente tenemos dos opciones: escribir un plugin al uso o añadir código en la librería personalizada functions.php. Optamos una vez más por la segunda opción.

Lo que hemos hecho ha sido escribir una función que comprueba el captcha, a partir de las instrucciones que encontramos en la documentación: http://code.google.com/apis/recaptcha/docs/php.html. Y, haciendo uso de los filtros de Wordpress (tremendamente útiles para poder personalizar su comportamiento sin tocar el "core"), asignamos la función recién creada al filtro "pre_comment_approved", que se ejecuta antes de verificar si el comentario debe o no aprobarse.


// Custom reCAPTCHA "plugin"
add_filter('pre_comment_approved', 'recaptcha_solved_comment');
function recaptcha_solved_comment($approved)
{
require_once(dirname(__FILE__) . '/lib/recaptcha/recaptchalib.php');

$privatekey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX';

$resp = recaptcha_check_answer($privatekey, $_SERVER['REMOTE_ADDR'], $_POST['recaptcha_challenge_field'], $_POST['recaptcha_response_field']);

if (!$resp->is_valid)
{
$approved = 'spam';
wp_die( __('Debes introducir el código de verificación correcto.') );
}
return $approved;
}

lunes, 25 de abril de 2011

Almacenamiento Local HTML5

Una de las (pocas) cosas que se echa de menos al desarrollar aplicaciones para la web es la persistencia. En esencia, el protocolo HTML es unidireccional (es decir, el servidor, a partir de una petición del navegador, genera una respuesta/página) y no guarda información de estado (es decir, no hay un "recuerdo" entre una página y la siguiente).

Esa es la teoría. En la práctica, con los años se han ido desarrollando mecanismos que permiten almacenar cierta información de manera persistente. En el lado del navegador (las cookies) y en el lado del servidor (las sesiones). Pero no son la solución real al problema de la persistencia. Las cookies tienen un límite de tamaño de 4KB y, además, se envían con cada petición que se hace al servidor, así que no es muy recomendable usarlas para almacenar demasiados datos. Por otro lado, el manejo de sesiones puede complicarse cuando tenemos múltiples frontales, ya que hay que habilitar algún mecanismo para que compartan dicha información.

Con las nuevas características de almacenamiento local de los navegadores modernos, eliminamos todos estos problemas de un plumazo.

En resumen:
  • Disponemos de 5MB de almacenamiento local por dominio, en el que podremos guardar pares clave-valor. Tanto la clave como el valor son cadenas de texto (así que cuidado a la hora de almacenar otros tipos de datos, ya que tendremos que realizar las conversiones adecuadas).
  • El almacenamiento es persistente, incluso al cerrar el navegador o cuando el navegador se cuelga o se cierra debido a un error.
  • Los datos no se envían al servidor bajo ningún concepto (salvo que el usuario los envíe).
  • Disponemos de getters y setters para cada clave, así como métodos para borrar el valor de una clave, consultar cuántos elementos tenemos almacenados o borrar todo el almacenamiento.
  • Cada vez que se hace una operación sobre el almacenamiento local y dicha operación suponga un cambio (entendiendo como que una operación que escribe en una clave el mismo valor que ya tenía, no lo produce) dispara un evento, que podemos escuchar y actuar en consecuencia.
  • Podemos utilizar el almacenamiento local para comunicar varias ventanas del navegador (en las que se ha abierto la misma aplicación web).
Hay una versión de almacenamiento local, llamada Almacenamiento de Sessión (session storage) que funciona exactamente igual salvo por el hecho de que, al terminar la sesión (por ejemplo, cerrando el navegador), todos los datos se pierden.

Como siempre, deberíamos detectar si el navegador usado dispone de estas características antes de usarlas.

Enlaces interesantes: