Archive for the 'Infinitos monos aporreando infinitos teclados' Category

Objetos maestros en PHP

Ya comenté el tema de usar clases “principales” para un proyecto… y ahora vuelvo con el mismo tema. Muy creativo, sí…

La idea es la de tener un objeto principal (maestro) con un constructor que crea dentro del propio objeto tantos objetos “internos” como hagan falta, pasándole por referencia su propio objeto al constuctor de los “objetos internos”.

Los “objetos internos” extienden a una plantilla de objeto, y esa plantilla contiene un constructor que a su vez “guarda” como referencia el parámetro pasado por el objeto principal.

Sí, es un lío, así que mejor verlo en código:

class AppObjectSkel {
  function __construct(&$parent) {
    $this->_parent = $parent;
    if(is_callable(array($this, 'init'))) $this->init();
  }
}

class AppDatabase extends AppObjectSkel {
  function init() {
    /* Aquí se inicializa la DB */
  }
}

class AppCache extends AppObjectSkel {
  /* Elemento de cache, no lo inicializamos en este ejemplo */
}

class Application {
  function __construct() {
    $this->database = new AppDatabase($this);
    $this->cache = new AppCache($this);
  }
}

De esta manera se puede acceder de un elemento a otro. Por ejemplo, desde AppCache se puede acceder a AppDatabase pasando por Application, simplemente usando $this->_parent->database. Al tratarse de un valor pasado por referencia, se puede acceder desde AppDatabase a AppCache y reflejar cambios en tiempo real.

Pero hay que tener en cuenta un pequeño detalle: los constructores. Debido a que se hereda de una clase maestra (AppObjectSkel), no se puede poner constructor de ningún tipo (ya sea __constructor o una función con el nombre de la clase), ya que PHP ejecutará únicamente el del objeto creado (AppCache, por ejemplo) y no el de AppObjectSkel (y mucho menos va a ejecutar dos constructores). Se puede evitar esto de varias formas: evitando AppObjectSkel en todos los casos y copiando el construct a cada vez, copiando el construct sólo cuando lo necesitamos (por que pisamos el construct de AppObjectSkel) o simplemente usar una función opcional (llamada init), como pongo en el ejemplo, que sólo se ejecuta si existe y se llama desde AppObjectSkel, a modo de constructor (un constructor invoca a otro).

Desde la propia aplicación simplemente hay que crear una nueva instancia del objeto Application ($app = new Application) y acceder a los diferentes objetos a partir del maestro ($app->db, $app->cache).

Esto llega a ser muy útil cuando la aplicación entera está divida en objetos (AppUsers, AppForums, AppProfiles...) y es necesario hacer transacciones entre los objetos. En lugar de crear una instancia para cada objeto cada vez que se necesitan (por ejemplo, instanciar AppCache desde AppUsers cuando hace falta usar memcache), se pueden instanciar una sola vez y acceder en un entorno protegido (Application, que vendría a ser un “contenedor” relativamente protegido de variables pisadas y globales erradas), a todos los objetos o variables que haga falta.

Con esto después se pueden hacer montones de cambios (instanciar una clase poco usada sólo cuando se necesita, hacer una especie de namespace para tener un cache durante la ejecución del programa…). Y es que ahí, la imaginación es el límite.

YQL o la gran base de datos que es Internet

Leyendo korben.info (un blog en francés) me he encontrado un post la mar de interesante sobre YQL.

YQL es "Yahoo! Query Language" y es básicamente un sistema de "queries"estructuradas que permite lanzar "consultas" contra Interner entero.

Esto se hace usando una estructura XML pura que es consultada mediante consultas YQL (pseudo-SQL) que pasan antes por Yahoo!, por ejemplo: (hay mejores ejemplos por ahí, merece la pena echar un vistazo)

SELECT * FROM twitter.user.status WHERE id=’adrinavarro’

SELECT * FROM search.web WHERE query=’vacaciones’

SELECT * FROM lastfm.tag WHERE tag=’beck’ AND api_key=’?’

La idea es muy sencilla y a más de uno le va a gustar. Hay una recopilación de las tablas en datatables.org. Para quién le interese probar, existe una consola de pruebas para ejecutar consultas y analizar el resultado.

Para más información, docs sobre YQL y ejemplos (en francés).

Mejorando lo mejorable

- Mejorando aquícerca (aquicerca.mobi), presentado por aquí

Por una parte, ‘detalles’: el CSS y el JavaScript ahora están comprimidos, asi que se debería notar cierta mejoría, sobre todo al usarlo con GPRS/3G, aunque –pese a todo– las librerías de Google Maps son muy pesadas (necesarias aunque sólo use una ínfima parte –el geocoder–). La salida de AJAX, por cierto, está comprimida por GZIP y pasa por un buffer, así que se queda menos ‘pillado’ cuando se busca un lugar. Y ya no es necesario hacer scroll para ocultar la barra de direcciones, puesto que se oculta automágicamente cuando no es necesaria.

Y en cuanto a lo importante: al ver los resultados, hay un icono de teléfono delante del nombre del lugar y un icono de mapa delante de la calle. Si es posible mostrar un mapa, la calle se vuelve ‘clicable’ y el icono de mapa está a todo color. Si está disponible el número de teléfono del lugar, se puede pinchar encima del nombre y el iPhone preguntará si se desea llamar. Sin embargo, cuando no es posible llamar o ver el mapa, los iconos se transparentan (y no hay enlace).

Luego, la otra novedad, y la más gorda: mapas, mapas, mapas. Aunque tampoco es un misterio… Al pinchar encima de la calle se muestra un callejero de Google Maps adaptado para móviles. Está preparado para ocupar toda la pantalla –ocultando la barra de direcciones– y cambia de orientación al girar el teléfono. Y tiene una imagen de carga muy clásica (plan AJAX). Luego, lo obvio: dos globitos. Uno rojo que indica la posición del usuario y uno verde que indica la posición del lugar seleccionado. Y para cerrar, basta con tocar el mapa.

Aquí cerca

Lo comenté en el post ‘A muerte con el mapa‘. Y la idea era bastante sencilla: traducir una ubicación a posición geográfica (reverse geocoding, que era uno de los temas que traté) y después buscar –por texto libre– cerca de esa ubicación.

Pues bien: se llama ‘aquícerca‘ (aquicerca.mobi) y está diseñado para usarse desde un iPhone/iPod Touch, sobre todo para cuando se está en movimiento (por ejemplo, cafés cerca de la parada de Metro en la que me encuentro). Cierto que para el iPhone ya existe Google Maps (y con el GPS!), pero en este caso uso el API de 11870.com que a mi parecer es bastante mejor… o lo prefiero.

Del lado técnico: usa el API de 11870, el API de Google Maps, MagpieRSS para parsear la salida del API de 11870 (no sé por qué pero SimpleXML se volvía tonto al parsear la salida RSS del API de 11870, era imposible conseguir los atributos geográficos o la calle), jQuery para la interacción con el usuaro (AJAX, bloqueo de formularios, transiciones entre páginas) y PHP del lado servidor (se limita a recibir la respuesta del Geocoder –que se ejecuta del lado del cliente, para evitar el capado de queries que tiene esta parte de Google Maps–, genera los formularios y devuelve los resultados de la búsqueda en 11870.com).

Como el navegador del iPhone de por sí es lentorro, está casi todo en AJAX para evitar cargar nuevas páginas. Por lo tanto, incluso para volver al estado inicial (tocando el logo) no se vuelve a pedir la página, simplemente se restaura por medio de JavaScript –y con unas transiciones mu chulas, hay que decirlo–.

Pese a que no hay ningún mapa que se muestre, usa el API de Google Maps para los módulos de geocoding, como comentaba en otro post. Se hace todo por medio de JavaScript (lo que inicialmente pensaba hacer del lado del servidor), y la verdad es que es bastante más rápido que procesar todo por PHP, sobre todo cuando se trata de enviar y recibir datos por 3G.

Mientras tanto, Miquel (gafeman) ha sacado su versión móvil para comil.us (lo comenta por aquí). La versión móvil suya es bastante más completa: usa Static Maps e incluye las fotos, aunque está limitado a unas búsquedas predefinidas (y saber a qué distancia estás del lugar) pero el mapa es una gran idea (y creo que en mi caso tampoco estaría mal tener un mapa del tipo “estás aquí, el lugar tal está aquí”). Y bueno, también por si quieres más de 5 posibilidades, claro (seguimos hablando de versiones móviles…).

La aplicación está preparada para usarse tanto en vertical como en horizontal (chorrada obvia) pero se maneja muy bien en vertical (no pierdes libertad de movimientos, con el pulgar va bien). Se puede añadir a la pantalla principal del iPhone/iPod touch apretando el botón inferior de + y seleccionando “Añadir a pantalla de inicio”, y ‘automágicamente’ aparecerá una bonita taza de café en vuestra lista de aplicaciones.

Por cierto, sí, el diseño: es CSS muy sencillo (a la par de cutre), el icono proviene de un maravilloso set de 128 iconos de WeFunction. Merece darse una vuelta por su blog, tienen trabajos incréibles.

La tipografía del título es la Alte Haas Grotesk, una sans-serif bastante agradable a la vista.

Asi que si tienes un iPhone o un iPod touch, ¿por qué no probarlo?, si hasta puede que te quede espacio en la pantalla principal para poner la bonita taza de café de aquícerca.mobi :-) .

A muerte con el mapa

Soy una leyenda. Me refiero a que posiblemente sea la persona más torpe a la hora de desplazarse que puede haber a este lado de tierra. Ni con el GPS del iPhone (sí, tengo un iPhone desde hace poco), ni con las indicaciones de Google Maps. Ni siquiera con las indicaciones por las que voy mendigando…

Vale, odio los mapas. Y soy una verdadera mierda a la hora de situarme, tengo el don de liarla siempre. Mi madre me lo dice, ’sólo tú puedes hacerlo hijo’. No se equivoca. ¿Debería sentirme orgulloso o preocuparme por ello, doctor?

Pero no es mi vida de lo que vengo a hablar, por quién me habéis tomado… Es que he vuelto a enfadarme con Google Maps. Bueno, ahora mismo no, pero sí hace unos meses y ahora que he retomado un poco el jugueteo con el API de Google Maps, es como tomarse mal una CocaCola. Vuelve y jode mucho.

Al turrón. Desde hace relativamente poco (bueno, ya hace bastante que está implementado) se puede usar el API de reverse geocoding desde JavaScript. Es sencillo: creas un nuevo objeto en plan geocoder = new GClientGeocoder(); y llamas a la función getLocations del mismo objeto.

Por dar un ejemplo:

geocoder = new GClientGeocoder();
geocoder.getLocations(latlng, function(addresses) {
if(addresses.Status.code != 200) {
alert("Ubicación no reconocida");
} else {
if(typeof(addresses.Placemark[0].AddressDetails.Country.
\
AdministrativeArea.SubAdministrativeArea.Locality.PostalCode) == "undefined") {
alert("No hemos podido obtener el código postal de este área, con lo que es posible que los resultados de tus búsquedas sean inexactos");
} else {
cp = addresses.Placemark[0].AddressDetails.Country. \

AdministrativeArea.SubAdministrativeArea.Locality.PostalCode. \
PostalCodeNumber;
};
};
);

(Nota mental: vaya pesadilla poner código en WordPress… Donde hay un \ hay que volver a juntar el código (quitando espacios, claro))

Todo este código asume que ya tienes un objeto llamado “latlng” que contiene las coordenadas de Latitud y Longitud que quieres convertir a código postal en este caso. Crear el objeto LatLng es muy fácil: latlng = new GLatLng(latitud, longitud);.

Aunque así parezca fácil, obtener la información reversa no es nada fácil, entre otras por que cambia el resultado si estás haciendo un reverse de un lugar en España, Alemania, Francia o Estados Unidos (jerarquía e informaciones algo diferentes). Por aquí hay un ejemplo básico de qué resultados da el Reverse Geocoding en XML.

Desde JavaScript, es algo así: del objeto se saca un array, matriz, tupla, quillostoquéeh de ‘PlaceMark’. Aquí asumimos el primero que es teóricamente el más preciso si no es el único. Dentro tenemos “AddressDetails”. Dentro de esto, “Country”. Dentro de “Country”, llega “AdministrativeArea”. Dentro “SubAdministrativeArea”. Dentro, “PostalCode”. Y ahí, finalmente, “PostalCodeNumber”.

Pese a que todo esto es y parece una pesadilla, obtener la dirección sin más se puede conseguir de una forma un poco más sencilla: addresses.Placemark[0].address;

Y repitiéndome de otras veces, esto no deja de ser una chuleta. Tamaño XL, pero sí… lo es.

Voy a ver si me pongo a hacer una aplicación sencillita para el iPhone, con el API de 11870. Mi idea era simplemente rellenar una “posición actual” con texto libre, pasarlo a coordenadas y pasarlo a reverso para confirmar en limpio (por código postal y dirección) la inserción realizada. Una vez ahí, un formulario de búsqueda libre que simplemente deje buscar a una distancia de nuestra posición actual (el API de 11870 permite búsquedas geográficas, la verdad es que mola un montón).

Voy a ver si no me pierdo demasiado (y de nuevo) con el GeoCoding. No es lugar para desorientados.

(Nota de pie: Sí, estoy copiando un poco –mucho– a Gafeman y su Comil.us, que por cierto, funciona genial y está muy bien –si no lo has hecho, échale un ojo–… pero le tengo ganas al API de Google Maps y a la de 11870, sólo sea por programar un poco para la plataforma webapp-móvil y exprimir al máximo el API JavaScript de Google Maps sin usar los propios mapas).