miércoles, 11 de febrero de 2015

Improving the use of a MongoDB database with the help of Symfony'sListeners

Sometimes applications need to filter large amounts of information to show to the user a small subset of relevant data.

However, when the amount data to filter is too large, it may not be feasible to filter the information retrieving the whole data into memory.

Read this article to learn about an alternative approach using a MongoDB document and Symfony listeners to limit the amount of data that needs to be traversed in memory.


Continue reading in PHPClasses.org

miércoles, 4 de febrero de 2015

Cálculo de las distancias entre coordenadas GPS

En varios de los últimos proyectos, sobre todo aquellos relacionados con aplicaciones móviles, he tenido que implementar un sistema de cálculo de distancias entre coordenadas GPS.

Para evitar en el futuro la repetitiva tarea de incorporar el código fuente he creado un repositorio que me va a permitir disfrutar de esa característica con una simple línea en el archivo composer.json de cada proyecto.

// composer.json
{
   "require":{
      "jlaso/gps": "dev-master"
   }
}


La clase la tienes disponible en github.

El funcionamiento de momento es muy sencillo, pues sólo está incluida la función que calcula la distancia. La idea es ir añadiendo poco a poco más funciones que tengan como base el GPS.


He preparado también los tests oportunos que podrás ejecutar con PhpUnit desde la raíz del proyecto.

Si crees que esta clase te es útil sólo te pido que la descargues a través de la página de PHPClasses y que la votes en su momento.

Espero vuestros comentarios.

lunes, 2 de febrero de 2015

Cómo conseguir que gettext funcione en php

A menudo necesitamos internacionalizar los programas que desarrollamos en PHP.

En mi libro Programación profesional en PHP con Slim, París y Twig trato este tema en el capítulo 13. Los ejemplos de como usarlo los podemos encontrar en el código de la aplicación de ejemplo My-simple-web.

Una de las formas de internacionalizar más extendida en los desarrollos web consiste en el uso de la librería ICU, Intl y gettext.

La función gettext en PHP tiene un alias (subrrayado) que hace más compacta la lectura del código, por que permite concentrarse en el texto y no en la función.

Veámos un ejemplo:


   print _('This is a text that have to be translated');    
   print gettext('This line is equivalent to the line above.');    
?>


Para que gettext pueda saber la equivalencia entre el mensaje que queremos mostrar y el que le estamos pasando necesitamos crear un catálogo de traducciones. El programa más extendido para hacer esto se llama PoEdit.


Aunque se puede poner como texto clave la cadena normal tal y como he mostrado en los ejemplos anteriores (esto se hace por si falla la traducción tener un texto en un lenguaje digamos, natural), cada vez más se está extendiendo, sobre todo debido a los frameworks, el uso de etiquetas en las cadenas claves. Esta técnica permite categorizar las entradas del catálogo, y no simplemente tener amontonadas las claves.


Así, un ejemplo habitual siguiendo estas directrices sería:


  
   print _("general.button.label.home");    
?>    


El lector podrá apreciar enseguida que el uso de esa nomenclatura permite tener una estructura arbórea muy conveniente. Así es como funciona por ejemplo www.tradukoj.com, mi proyecto para ayudar a los desarrolladores a centralizar sus cadenas para traducir.

Una vez entendidos estos principios básicos, y teniendo entendido que queremos aprovecharnos de ellos en nuestros desarrollos, vamos a necesitar configurar nuestro intérprete de PHP para que acepte esta orden, ya que no forma parte de la SPL.

Lo habitual es que tengamos que instalar en el sistema la libreria ICU, INTL y el soporte para ambas en PHP.

Vamos a ver los diferentes casos que nos podemos encontrar en función del sistema operativo.

Windows

En este sistema operativo lo habitual es disponer de soporte para PHP mediante alguna de las aplicaciones que vienen como un todo en uno. También conocidas como WAMP (de su homólogo LAMP: Linux-Apache-Mysql-PHP), tenemos con el mismo nombre WAMP; AppServ y XAMPP.

En todas ellas la activación de una librería estándar suele ser un paso muy sencillo. Basta con marcar la librería en la configuración o irse directamente al archivo php.ini y descomentar la línea:
;extension=php_intl.dll


Concretamente, para el caso de Xampp puedes encontrar enlace directo a la edición de php.ini en el programa Panel de control de Xampp


xampp-config

Linux (Ubuntu/Centos y variantes)

Para instalar soporte de idiomas en el S.O Linux, si es que no lo tenemos ya, será suficiente con instalar INTL, ICU y el conector para PHP.



Ubuntu:

sudo apt-get install intl icu php5-intl


Centos:

yum install intl icu php5-intl


OsX

En función de si tenemos MacPorts o Brew instalaremos el soporte de idiomas de esta manera:


Mac Ports:

sudo port install php5-intl


Brew:

brew install php5-intl


En ambos casos para activar la extensión hay que editar php.ini y agregar o descomentar esta línea:

extension=intl.so


En todos los sistemas operativos podemos ver que php.ini usa nuestro sistema lanzando este comando desde la terminal:

php --ini


Ten en cuenta en todo caso que algunos sistemas usan un php.ini para el cli (interfaz de consola) y otro para el servidor web (apache normalmente).

Ahora sólo nos queda comprobar que funciona.

Para que el sistema operativo sepa que idioma estamos esperando cuando le mandamos gettext, necesitamos configurarlo antes que nada, por ello, de manera habitual, en el bootstrap de nuestra aplicación haremos algo como lo que tenemos aquí:


   @bindtextdomain('default', dirname(__FILE__).'/');    
   @textdomain ('default');    
   $langs = array (    
    'es' => 'ES',    
    'en' => 'GB',    
   );    
   $code = isset($_REQUEST['lang'])?$_REQUEST['lang']:'es';    
   if (isset($langs[$code]))    
     $iso_code = $code.'_'.$langs[$code];    
   else{    
     $code = "es";    
     $iso_code = 'es_ES';    
   }    
   if (isset($_SESSION['lang'])) $_SESSION['lang']=$code;    
   putenv ('LANGUAGE='.$iso_code);    
   putenv ("LC_ALL=$iso_code");    
   setlocale(LC_ALL, $iso_code);    
?>



Recuerda: si te da algún error como este:

Fatal error: Call to undefined function _() in ... on line x

Vuelve a repasar la configuración.


En todo caso, si se te resiste el uso de esta librería en local y en producción te funciona correctamente, no es nada descabellado utilizar este truco:


if(!function_exists('_')){
    function _($key){ return $key; }
}

Esto no te traducirá los textos, pero al menos no te romperá el código.

Espero vuestros comentarios.