php

El staff de PHP responde a los consejos de Google

Esta semana Google ha presentado (Estos tíos no paran) una serie de consejos para mejorar el rendimiento de nuestras páginas web. ¡Escalabilidad, escalabilidad, escalabilidad! Prácticamente no lo he leído, ya que imagino que la mayoría de los trucos serán muy similares a los que Yahoo! ofrece desde hace tiempo (Por cierto, viva Yslow :D (Tampoco he probado el equivalente de Google, Page Speed)).

Lo que sí he hecho es revisar por encima los consejos que Google ofrece sobre PHP. Hasta yo, que no conozco prácticamente nada de las entrañas de PHP, me he percatado de que esos consejos eran a menudo erróneos, bulos que circulan, o relativos a versiones de PHP muy antiguas.

El staff de PHP ha contestado

Resumen de lo que sí son hechos:

  1. Don’t copy variables for no reason – Falso. El Zend Engine hace que cuando copias una variable, ambas apuntan a lo mismo salvo que se realicen modificaciones. Por tanto, la memoria usada será y es la misma.
  2. Use single-quotes for strings – Falso. Hace tiempo que el rendimiento es prácticamente equivalente al usar dobles comillas que comillas simples (Personalmente uso comillas simples por costumbre desde tiempo ha).
  3. Use echo to print – No siempre es mejor.
  4. Don’t use concatenation with echo – Falso. Ocurre al revés. Es más efectiva la concatenación que el uso de múltiples argumentos.
  5. Use switch/case instead of if/else – Sin sentido. La diferencia entre uno y otro es de estilo, no de rendimiento.

En fin, al menos todos estos tips son de buena fé :)

Páginas web modulares en PHP con Zend Framework

Jeroen Keppens está escribiendo en su blog una serie de artículos muy muy interesantes acerca de cómo implementar módulos autocontenidos empleando Zend Framework. Esta estrategia es increíblemente potente ya que, al ser módulos autocontenidos, podremos copiarlos directamente a un proyecto nuevo y ya funcionarán. Si se programan de forma suficientemente versátil, se podrán encajar entre sí como piezas de un lego que dan forma a la aplicación final. ¿No es genial? :)

En el primero de ellos nos muestra cómo crear el esqueleto de un módulo. Los pasos básicos a seguir son:

  1. zf create project .
  2. zf create module nombremodulo
  3. zf create controller index 1 nombremodulo
    1. Bug – Renombrar el nombre de la clase del controlador añadiendo el prefijo Nombremodulo_.
  4. Añadir configuración de módulos en application.ini:
    resources.frontController.moduleDirectory = APPLICATION_PATH “/modules”
    resources.modules[] =

Básicamente con eso ya lo tenemos, accesible en el path relativo /nombremodulo. ¡Ha sido sencillo!

Por supuesto cada módulo se comporta como una mini-aplicación, por lo que podremos completarlo con su propio fichero Bootstrap.php. Nota: A mi me surgió la duda de cómo poder asegurarse de que un determinado método del Bootstrap principal se ha ejecutado (Por ejemplo, el resource db). Nada más tenemos que llamar a $this->getApplication() y obtendremos el Bootstrap principal. ¿Y esto por qué? Porque al estar contextualizados dentro de un módulo, no obtenemos el objeto Application como cabría esperar, sino el Bootstrap.

Llevado por la emoción, y teniendo en cuenta varios proyectos que tengo pendientes, me puse manos a la obra a programar mi primer módulo autocontenido: Usuarios. Será un módulo muy configurable que permita manejar sesiones, mostrar captchas, registro libre de usuarios o sólo por parte del administrador, acl, facebook connect, y más. Cuando tenga algo presentable lo liberaré :)

El caso, necesitaba que mi módulo fuera configurable. Por ejemplo, ¿se muestran captchas para hacer login? ¿Tras cuantos intentos fallidos? ¿Y qué tipo de captcha? ¿Dónde se almacenan los usuarios? ¿Y en qué campos? Para resolver eso necesitaba de un fichero de configuración. En lugar de tratar de que el propio módulo ejecute sus propios resources en su Bootstrap, opté por la solución fácil: Cargar a mano el fichero de configuración, y revisar sus opciones.

Pero de nuevo Jeroen Keppens ha dado en el clavo proponiendo la solución pro. En su segundo artículo sugiere un ingenioso y completo método para manejar configuraciones a nivel de módulo. No implementa aun manejo de errores, pues se trata de una pre-beta, pero ilustra a la perfección cómo solucionarlo.

Sólo le veo una pega a las soluciones que propone: Dependen en gran parte de su biblioteca extendida, es decir, es necesario tener accesibles a nivel de aplicación numerosas clases desarrolladas por él. Por supuesto, siempre hay una segunda opinión, y en mi caso ubico dichas bibliotecas en /modules/modulename/library/, pese a que en un futuro eso suponga ficheros repetidos. ¿No se trataba de tener módulos autocontenidos? ;)

Liberado Zend Framework 1.8.4 y más

A través del Developer Center de Zend me entero de que hoy se ha liberado la última versión estable de Zend Framework. Esta release de mantenimiento ha corregido más de 50 tickets abiertos en 20 componentes distintos. Con un poco de suerte ya podremos disfrutar de la rama 1.8 sin tantos workarounds para salir del paso.

Por lo pronto, y si utilizáis svn, ya tardáis en hacer un svn up :)

A finales del próximo mes de julio lanzarán la versión 1.9.0. ¿Qué está previsto que traiga? Pues bastantes cosas, como por ejemplo un lector de feeds mucho más completo y elaborado, enrutador para peticiones de tipo REST, soporte LDAP, patrón factory en Zend_Log, etc.

Además, acaban de lanzar también un visor de roadmap que estará activo a partir de ahora para todas las futuras releases. Si bien esta herramienta será muy útil tanto para fieles como para curiosos, no contará con fecha de lanzamiento, pues tal y como explican en su blog, es muy complicado estimar fechas cuando todo el trabajo lo realizan voluntarios en su tiempo libre.

Edit: Acabo de comprobar que además han corregido la creación de controladores en modulos desde la utilidad en línea zf. ¡Bravo! :)

to goto or not to goto

Hace 5 días PHP lanzó la versión 5.2.10, centrada sobre todo en corregir fallos de seguridad. Un día después, el 19 de junio, lanzaron la RC4 de PHP 5.3.0, algo así como una versión de transición entre PHP 5 y el esperada PHP6. ¿Qué novedades traerá PHP 5.3.0? Bueno, de eso ya se ha hablado mucho, como por ejemplo namespaces (¡Al fin!), late static binding y closures entre otras muchas cosas. ¿Qué cosas exactamente? Sigue leyendo…

Una de ellas es, ni más ni menos, que la estructura de control goto. Así es amigos. Si PHP no es suficientemente sencillo, que incluso poniendo tu perro a pisar el teclado se sacará un programa que ejecute sin problemas, ahora para facilitar el trabajo a los muchos entusiastas del spaguetti code nos presentan el goto.

Sin duda esta estructura es muy controvertida. Bien usada permite construír código más limpio y legible. Pero ahí radica el problema… Pocas veces está justificado su uso.

En fin, al igual que en la documentación de PHP, os pongo una tira cómica cortesía de xkcd.

goto

Nueva página web de Torrijos

captura5El pasado día 11 de junio se presentó en el salón de plenos del Palacio de Pedro I la nueva página web del Ayuntamiento de Torrijos. Este momento marcó un punto y aparte en este nuevo portal para el ciudadano. Durante los últimos meses hemos dedicado muchísimos esfuerzos, ganas e ilusión a este proyecto, y creo que hemos logrado nuestro objetivo: Ofrecer una web renovada con contenidos de actualidad que sustituyera a la antigua.

Singleton serializado en sesión de PHP

Llevo un par de días liado programando desde cero una pequeña tienda online (Sin pasarelas ni florituras). Entre los hitos que tenía para hoy, el más importante es crear el carrito de la compra. He buscado por el todo poderoso, pero todas las soluciones que veía me parecían ineficientes o feas. No quería almacenar el carrito de forma “permanente” en la base de datos, de modo que lo lógico me parecía usar la memoria de las sesiones. Evidentemente el carrito debía ser un singleton, pero ¿cómo hacer que se serialice automáticamente en memoria?

Echemos un primer vistazo a un singleton en PHP:

class Example
{
    // Hold an instance of the class
    private static $instance;

    // A private constructor; prevents direct creation of object
    private function __construct()
    {
        echo 'I am constructed';
    }

    // The singleton method
    public static function singleton()
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }

    // Example method
    public function bark()
    {
        echo 'Woof!';
    }

    // Prevent users to clone the instance
    public function __clone()
    {
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }

}

Sencillo, verdad? :) Pero este es el esqueleto de un singleton básico. Se declara como privado el constructor, de forma que si necesitas una instancia del objeto debas hacerlo necesariamente por el método estático Example::singleton(). Este método construye una nueva instancia, o bien devuelve la que ya había (Almacenada en el atributo estático $instance). Sin embargo la clase que yo necesito debe cargarse por defecto de memoria, y almacenar el objeto de nuevo cuando éste se destruya. La solución aquí:

class ShoppingCart
{

    private $_items;
    private static $_instance;
    private static $_namespace = "spp";

    private function __construct()
    {
        $this->_items = Array();
    }

    public function __destruct()
    {
        $shopping = new Zend_Session_Namespace(self::$_namespace);
        $shopping->object = serialize(self::$_instance);
    }

    public function __clone() {
        throw new Exception("Cannot clone singleton!");
    }

    public static function singleton()
    {
        $shopping = new Zend_Session_Namespace(self::$_namespace);

        if (!isset(self::$_instance)) {
            if(isset($shopping->object)) {
                self::$_instance = unserialize($shopping->object);
            } else {
                $c = __CLASS__;
                self::$_instance = new $c;
            }
        }

        return self::$_instance;
    }

    public function addItem($id, $quantity)
    {
        // Código que añade un nuevo item
    }

    public function removeItem($id)
    {
        // Código que elimina un item
    }

    // Resto de funciones del carrito de la compra
}

Básicamente funciona igual, excepto que antes de crear un nuevo objeto, comprueba si hay alguno en el espacio de nombres de memoria asignado en el atributo estático $_namespace. Igualmente, cuando el objeto se destruye automáticamente por el recolector de basura, se serializa para guardarse la nueva versión en memoria.

Es importante darse cuenta de esto último: El método __destruct() no funcionará si ya hemos finalizado la sesión del usuario mediante session_write_close(). Por esa razón, en algunos casos tendremos que llamar explícitamente al destructor antes de que se cierre la sesión. Resulta que el método para redirigir a otra página Zend_Controller_Action::_redirect($url) cierra la sesión. Me he vuelto loco hasta que he averiguado la razón. Se corrige simplemente llamando a ShoppingCart::__destructor() antes de hacer la redirección.

Zend Framework 1.8.0 Released

¡Qué gran noticia! :) Ha sido liberada la nueva versión de Zend Framework. Como principales novedades nos ofrece la posibilidad de utilizar Zend Tool, la herramienta de consola para hacer el trabajo sucio por nosotros, y además una nueva capa para servicios de computación nube (ugh!) en Amazon.

Desde la famosa aparición de Ruby on Rails en el año 2004, no han parado de aparecer nuevos frameworks de desarrollo implementando las fantásticas ideas alrededor de RoR. En PHP, por nombrar algunos, pronto se hicieron muy populares CakePHP o Symphony. Pero por otra parte tenemos a Zend, la empresa detrás del motor intérprete de PHP (En consecuencia, gozan de un principio de autoridad más que merecido en dicho lenguaje). Corría el año 2005 cuando lanzaron la primera versión de su framework.

Pese a que aun hoy se podría decir que carece de muchas funcionalidades que hace años son comunes hasta en los frameworks más espartanos, a título personal Zend Framework fue el que me cautivó desde el primer momento: Su funcionamiento es totalmente modular. A diferencia de sus competidores, no obliga a dar el salto de la noche a la mañana, sino que permite ir adoptando poco a poco sus utilidades, instalándolas bajo demanda. Lenta pero implacablemente vas cayendo presa de sus encantos, hasta que ya un día te das cuenta de que has dejado de programar en PHP; Ahora programas en ZF :)

Una de las ventajas de que sea tan increíblemente modular es que puedes dar el salto a su sistema MVC poco a poco. Primero empiezas con un bootstrap y controladres básicos, luego vas dominando las vistas y los layouts, hasta que finalmente un día añades modelos de datos, y modificas el enrutador a tu antojo. Todo ello controlando desde el primer momento qué estructura de directorios emplear, o de qué manera funcionará la maquinaria.

No sé a vosotros, pero yo una de las cosas que mas detesto de todas las novedosas herramientas de programación que surgen últimamente es la magia. Sigues los tutoriales y piensas “¡Dios mio! ¡He creado un blog en 10 minutos! Pero no tengo ni idea de cómo“. Y eso no deja buen sabor de boca. ¿Que ocurre si necesitas alterar levemente el funcionamiento de la aplicación que se crea en el tutorial? Pues que sudas tinta y en el peor de los casos vuelves acobardado a tu metodología de siempre. Esto no pasa zon ZF :)

Pero al lío, que mi disertación sobre frameworks se ha alargado. ¿Por qué me emociona tanto la nueva release? Porque, tras varios meses programando con él, acaba de salir el script de consola que permite crear los andamios de tu aplicación (Scaffolding). Pero, como todo en Zend, es totalmente personalizable. Puedes configurar el funcionamiento por defecto del script mediante el Provider y el Manifest.

Además, y cosa que me encanta, esta herramienta ha sido lanzada junto con una nueva arquitectura de aplicaciones: Zend_Application. Básicamente encapsula las funcionalidades del fichero bootstraping en un recurso reutilizable dentro de un objeto. O visto desde otra perspectiva, es el objeto principal con su método main(). Orientación a objetos al poder!

Respecto al apartado de la computación nube… No tengo mucho que comentar. Me gustan las infraestructuras estándar (Como LAMP), y eso de volcar mis recursos en plataformas propietarias, heterogéneas, y sólo en manos de un proveedor, no me gusta nada. Así que por el momento dejo el cloud computing a los gurús de las blackberries.

Seguridad en PHP

En este pequeño post voy a dar un repaso a algo que la mayoría de programadores web ya saben, pero para no olvidarlo, y por si a alguien le viene bien, voy a resumir los principales puntos en los que debemos cuidar la seguridad de nuestras aplicaciones en PHP.

Estándar de código en PHP

Los convenios son buenos. Ayudan a resolver siempre de una misma forma situaciones similares. Cada programador/proyecto tiene sus propios convenios de programación. En este artículo voy a contar los mios cuando desarrollo en PHP.

Sangrado y edición

No utilizo el caracter tabulador. En su lugar, empleo 3 espacios. Motivo: El caracter tabulador (t) no se muestra igual en todos los lectores de ficheros.

No utilizo más de 80 caracteres de ancho por línea. Motivo: El código es mucho más legible y cómo de imprimir.

Si una línea excede de 80 caracteres:

preg_match('expresion regular de la muerte larga larga', $cadena, $match);

quizás meto la cadena larga en una variable

$reg = 'expresion regular de la muerte larga larga';
preg_match($reg, $cadena, $match);

o si la cadena es muy larga, concateno las partes

$reg = 'expresion regular de ';
$reg .= 'la muerte larga larga';
preg_match($reg, $cadena, $match);

o si no es tan larga, divido en lineas la función

preg_match('expresion regular de la muerte larga larga',
   $cadena, $match);

¿Y con los ifs de muchas condiciones que sobrepasan los 80 caracteres?

if ($condicion1 && $condicion2 && $condicion3 && $condicion4) {
   // código
}

pasa a ser

if ($condicion1 &&
   $condicion2 &&
   $condicion3 &&
   $condicion4)
{
   // código
}

Bloques de código

Las llaves, para definir bloques de código, siempre las coloco así:

expresión {
   // código
}

salvo que la expresión exceda de 80 caracteres, en cuyo caso lo hago así:

expresión larga
   muy larga
{
   // código
}

En este segundo caso la razón de pasar la llave a la izquierda es poder distinguir dóde empieza el bloque de código. Sin embargo, en el primer caso lo pongo al final de la línea por costumbre.

Nombres

Por supuesto deben ser descriptivos, salvo algunas excepciones, como variables de contadores.

Los nombres de funciones, métodos y clases, siempre procuro ponerlos en CamelCase, esto es, eliminando los espacios y poniendo la primera letra de cada palabra en mayúscula. En funciones y métodos, la primera letra de todas es minúscula, y en el caso de clases, en mayúscula.

Por ejemplo

class Car {
   public function getSpeed() {
   }
}

En el caso de atributos y variables suelo emplear palabras en minúsculas delimitadas por guiones bajos, por ejemplo:

private $main_container;

Las constantes, como no, en mayúsculas.

Y por último, los nombres de ficheros, que los pongo también sustituyendo espacios por guiones bajos, por ejemplo foo_bar.php.

Cadenas de texto

Nunca empotro variables dentro de una cadena entrecomillada. Por ejemplo

"Hola $nombre, bienvenido"

Lo pondría como

'Hola ' . $nombre . ', bienvenido'

Si bien hace unos años la diferencia de rendimiento al utilizar comillas dobles o simples era muy notable, debido a que las dobles permiten interpretar las variables dentro de ellas, hoy día es un obstáculo superado para PHP. En cualquier caso, sigo prefiriendo comillas simples salvo que sea imprescindible.

Nunca separo una misma cadena en varias líneas. En su lugar concateno las partes.

Comentarios

Los ficheros, clases y métodos los documento con comentarios con phpDocumentor.

Para comentar trozos de código utilizo doble barra (//), aunque exceda dos líneas:

// Este comentario tiene dos líneas, pero
// aun así no utilizo comentarios multilínea

Para poner comentarios importantes, por ejemplo, informando de qué me queda por hacer en un código sin acabar, lo pongo con tres barras (///):

/// Terminar la validación de variables introducidas por el usuario

Y para poner avisos importantes con algo que sé que hasta dentro de un tiempo no me volveré a encontrar, pongo:

/// NOTE: recuerda eliminar este método

Miscelánea

Por último, las etiquetas de PHP <?php y ?>, que tan poquito me gustan, las escribo siempre como <?php y ?> salvo en el caso de hacer un echo, que utilizo la forma abreviada <?=$var?>. Esto último está desrecomendado, ya que por ejemplo, daría error la primera línea de un fichero en XML:

<?xml ?>

Además muchos servicios de alojamiento no permiten las etiquetas cortas de PHP.

Y respecto al importado de ficheros, tenemos include(), include_once(), require() y require_once(). Siempre utilizo los terminados en once(), ya que de ese modo puedo llamar varias veces sin preocuparme a un mismo fichero. Además, procuro usar siempre require_once() (Aunque a menudo se me olvida) pues, a diferencia de include, require lanza un error que interrumpe la ejecución. Y no queremos que nuestra aplicación continue la ejecución si falta un fichero importante :)

Algunos estándares

Cada framework y casi cada proyecto tienen su propio estándar. A continuación enumero algunos:

SVG y la web

Los mapas de bits no escalan (Y nunca mejor dicho), por lo que en numerosas situaciones es preferible utilizar imágenes vectoriales. Por ejemplo, los escritorios de Linux ya están permitiendo emplear iconos vectoriales, de modo que se vean siempre bien definidos independientemente de su tamaño o de la resolución de la pantalla. Existen muchos formatos propietarios, pero, como siempre, para garantizar la interoperabilidad es preferible utilizar estándares, y ese es el formato SVG, que es un lenguaje para describir imágenes y aplicaciones gráficas en XML.

En el mundo web es igualmente interesante poder empotrar imágenes dinámicas generadas mediante SVG. Por ejemplo, hace un tiempo quise hacer unos mapas de densidades de población por municipios generados de forma automática para la Wikipedia. En realidad es muy sencillo. En ese caso podemos partir de una imagen con un objeto por cada término municipal, y mediante un editor de SVG (Por ejemplo, Inkscape) editar las propiedades del objeto y establecer como ID el código postal del municipio. De ese modo, podremos acceder mediante DOM al objeto que representa cada término municipal para posteriormente establecer el color de fondo dependiendo de su densidad (Expresiones regulares al rescate).
Mapa de España por provincias generado utilizando PHP y SVG

Y es que a veces nos complicamos mucho la vida, como por ejemplo dibujando a pelo polígonos sobre la API de Google Maps, cuando incluso podemos empotrar directamente imágenes SVG en un mapa de Google.

A día de hoy, la mayoría de los navegadores permiten visualizar directamente imágenes vectoriales SVG dentro de un documento XHTML, pero como a menudo sucede, Internet Explorer no renderiza de forma nativa SVG. ¿Qué podemos hacer en esos casos? Muy sencillo. Convertir dinámicamente a un mapa de bits. En el caso de PHP no he encontrado ninguna biblioteca o clase que permita la conversión de forma eficaz, sin embargo existen utilidades en la línea de comandos a las que podemos llamar para que realicen conviertan al formato deseado (Como el propio Inkscape o la utilidad convert de ImageMagick).