Javascript para programadores impacientes

JavaScript for impatient programmers — a pesar del título, explica con harto detalle incluso los aspectos más básicos del lenguaje.

Está actualizado hasta ES 2019 por lo que es especialmente útil para refrescar cosas de sintaxis y nuevas funcionalidades que se han ido incorporando al lenguaje.

El libro está prácticamente entero, sólo hay un par de capítulos bonus que son de pago.

Trabajar con fechas en MySQL

Trabajar con fechas es una tarea que al estar sujeta a tantas reglas especiales (meses con distinta cantidad de días, años bisiestos, comienzo de mes a media semana, etc) puede ser muy compleja si lo intentamos abordar sin el apoyo de una buena base.

Anteriormente he escrito sobre cómo trabajar con fechas en PHP y en Javascript: en ambos casos contamos con el concepto de fechas como objetos, lo que ordena y facilita bastante su manipulación a través de los métodos propios de cada lenguaje.

En MySQL existe a su vez un concepto de fechas y tiempos como tipos de datos con sus propias características, y junto con ellos, un montón de funciones que nos pueden servir para realizar distintos cálculos y operaciones al realizar consultas.

Continue reading “Trabajar con fechas en MySQL”

Cargar imágenes de sitio remoto a través de proxy inverso con nginx

Independiente del proyecto, CMS o framework sobre el que estés trabajando, contar con una copia local de desarrollo es fundamental.

Aunque replicar configuraciones y bases de datos es algo relativamente sencillo, para proyectos de mediana o gran envergadura se hace especialmente complejo contar con todas las imágenes y archivos subidos por usuarios, por lo que es necesario recurrir a otras alternativas para lograr una réplica útil.

Por supuesto, una alternativa es simplemente realizar una copia mediante rsync u otro mecanismo, pero la librería de imágenes de un sitio grande puede llegar a pesar varias decenas de gigas; por eso la opción de acceder a estos archivos por un proxy resulta muy conveniente y práctica.

Ejemplos de configuración para WordPress

En primer lugar tienes que verificar que nginx tiene el soporte para el módulo de proxy, lo que puedes chequear ejecutando nginx -V desde la consola. Si estás usando la versión que viene en los repositorios de Ubuntu, deberías tenerlo.

Ahora lo más sencillo, para el caso de un sitio único (sin multisite).

https://gist.github.com/felipelavinz/9776262

Y algo más complejo, para multisitio con subdominios:

https://gist.github.com/felipelavinz/9776360

Otro escenario de uso muy útil es para réplicas de sitios que se utilizan como QA.

Vale la pena indicar que lo mismo se puede conseguir con otros servidores web; por ejemplo con Apache. Lighttpd también tiene un módulo de proxy, por lo que también se debería poder.

Generar IDs alfanuméricos con PHP o Javascript

Recientemente necesitaba generar identificadores únicos, breves, que no fueran dependientes del contenido, y no aleatorios… si bien podrían haber sido simplemente números enteros, además quería que no fueran explícitamente secuenciales.

Finalmente me decidí por utilizar números en base 36, una técnica bastante utilizada por servicios para acortar URLs, como TinyURL y otros. La gracia de este sistema es que puede representar números grandes en una secuencia de letras y números; y se puede lograr tanto en PHP como en Javascript (además de un montón de otros lenguajes).

Continue reading “Generar IDs alfanuméricos con PHP o Javascript”

WordPress: get_post_meta() devuelve resultados en orden aleatorio

Una de las funciones más útiles de WordPress es get_post_meta( ), que nos permite obtener alguno de los metadatos asociados a una entrada.

Si deseamos obtener un metadato único, utilizamos get_post_meta( $post->ID, 'meta_key', true ), y si es múltiple, get_post_meta( $post->ID, 'meta_key', false), y aquí nos podemos topar un problema importante, ya que en algunas circunstancias el orden en que devuelve los resultados es aleatorio.

La razón de esto es que al ejecutar la función, WordPress carga la información de todos los metadatos asociados a la entrada en el caché de objetos, pero esta consulta no incluye un ORDER BY que permita determinar el orden, y aunque es posible especificar un orden predeterminado en una tabla, los datos de la tabla no permanecen en el mismo orden al actualizarla (por eso es que el orden es aleatorio)… esto es, si estás utilizando tablas MyISAM.

Sin embargo, existe un workaround para evitar este problema, ya que al utilizar tablas InnoDB, el orden en que se devuelven los resultados al hacer una consulta sin ORDER BY siempre es el mismo: de forma ascendente según su PRIMARY KEY.

O sea, si tienes este problema, te lo puedes ahorrar fácilmente con ALTER TABLE wp_postmeta ENGINE = InnoDB.

¡Ah! Por cierto, este problema ya está reportado como bug, y la solución (o sea, el ORDER BY) debiese venir incluído en WordPress 3.8; ¡yei!

Usando decoradores para extender WP_Post

La clase WP_Post recientemente introducida en WordPress 3.5 permite facilitar muchas tareas comunes en el desarrollo sobre este CMS, en particular el trabajo con campos personalizados almacenados en la tabla {$wpdb->prefix}postmeta.

Sin embargo, la forma en que está implementada esta clase aparentemente pone una limitante importante, ya que al estar definida como final no puede ser extendida mediante herencia:

class MiPost extends WP_Post{}
// Error Fatal: Class MiPost may not inherit from final class

Sin embargo, y aunque quizás no parezca obvio, es totalmente posible extender la funcionalidad de esta clase no utilizando herencia sino composición, por ejemplo, utilizando el patrón Decorator.

abstract class PostDecorator{
	
	/**
	 * Almacena el objeto post
	 * @access private
	 */
	private $post;
	
	/**
	 * @param object $post Un objeto de tipo WP_Post
	 */
	public function __construct( WP_Post $post ){
		$this->post = $post;
	}
}


class PostProyecto extends PostDecorator{
	
	/**
	 * @param string Nombre de la propiedad que se desea obtener
	 * @return string Valor de la propiedad
	 */
	public function __get( $key ){
		// permite acceso como $objeto->autor
		if ( $key === 'autor' )
			return $this->getAuthor();

		// si no corresponde a la funcionalidad que estamos agregando
		// podemos aprovechar el método __get() del objeto post
		return $this->post->{ $key };
	}

	/**
	 * @return string Nombre del autor o enlace
	 */
	public function getAuthor(){
		// el nombre del autor se almacena como un post meta con clave "_author"
		$author     = $this->post->_author;
		// la url está en un post meta con clave "_author_url"
		$author_url = $this->post->_author_url;
		return ( $author_url ) ? '<a href="'. esc_url($author_url) .'">'. $author .'</a>' : $author;
	}

}



$project_post = get_post(123);
$project = new PostProyecto( $project_post );

echo $project->autor;
// <a href="http://felipe.lv">Felipe</a>

De este modo, podríamos crear una clase para cada tipo personalizado de contenido, de modo de poder separar ordenadamente la lógica de la presentación y obtener una sintaxis muy clara y simple.

Objetos de posts de WordPress y la clase WP_Post

Una de las novedades más interesantes para desarrolladores que trae WordPress 3.5 es que a partir de esta versión los objetos tipo “post” ya no son objetos estándares de PHP (stdClass) sino instancias de WP_Post.

Por supuesto, este cambio está asociado a algunas ventajas inmediatas, relacionadas con una mejor performance y una optimización en que estos objetos se pueden almacenar en la caché de objetos (sobre todo si estás usando una caché externa, como APC, XCache o memcached). Esto es en parte debido a la utilización de métodos mágicos, tales como __isset( $key ), y el que resulta mucho más interesante, __get( $key ), que por ejemplo, permite cargar los “ancestros” de una entrada sobre demanda (con “lazy loading”), pero además tiene la posiblidad de cargar cualquier campo personalizado con la misma técnica.

En la práctica, esto significa que la utilización de datos de postmeta es muchísimo más sencilla. Por ejemplo:

<?php

// WordPress pre-3.5
// Deseo mostrar el campo personalizado "_ubicacion"
$ubicacion = get_post_meta( $post->ID, '_ubicacion', true );
echo $ubicacion;

// WordPres 3.5+
echo $post->_ubicacion;

Es decir, puedes acceder cualquier postmeta simplemente indicando el correspondiente meta_key como propiedad del objeto $post… ¡más conveniente, imposible!

Y si como yo tienes una “sana preocupación” por la performance de esta funcionalidad, puedes estar tranquilo: desde hace varias versiones WordPress carga en caché toda la información de postmeta al acceder a cualquier campo personalizado, lo que significa que no estará realizando una consulta a la base de datos cada vez que debas acceder a una propiedad de postmeta.

El único “pero” de la implementación de la clase WP_Post es que está marcada en el core como una clase final, por lo que si deseas utilizarla en un contexto mayor, no podrás extender la clase mediante herencia (como en MiClase extends WP_Post), sino que deberás hacerlo mediante composición, un patrón de diseño que quizás es un poco menos obvio… pero eso es motivo para otro post.

PHP: The Right Way

PHP ha cambiado profundamente durante su existencia, lo que nos motiva a actualizar nuestros hábitos al escribirlo y aprovechar sus nuevas funcionalidades en la implementación de buenas prácticas. PHP: The Right Way es una referencia rápida de buenas prácticas, estándares de código y enlaces a tutoriales actualizados en el manejo de este lenguaje… si desarrollas sobre WordPress, márcalo como lectura obligatoria.