Archivo de la etiqueta: php

FirePHP, otra herramienta de depuración de PHP

Llevo años usando Xdebug para hacer depuración de PHP, pero últimamente estoy ocupando algo más.

FirePHP está compuesto de 2 partes, una librería PHP (puede ser usada en versión orientada a objetos o en funciones). La otra parte es una extensión para Firefox (también hay otras extensiones de terceros para otros navegadores, como Google Chrome), que a su vez extiende la funcionalidad de la ya conocida extensión Firebug.

¿Para que sirve?

Firebug añade un panel donde se puede llevar control de varios tipos de error que son detectados por el navegador, sobre todo en tiempo de ejecución como lo es con javascript de las páginas web o también de las mismas extensiones de Firefox.

FirePHP añade algo más. Por el lado de la librería, Firebug es capaz de enviar información de depuración a través de las cabeceras HTTP y no en el contenido (como lo hace el reemplazo de la gestión de errores nativa de PHP que añade Xdebug). Esto tiene varias ventajas, por ejemplo:

  • Evita que al desplegarse errores sobre el HTML de un sitio, este se descuadre su diseño, o debido al diseño, no pueda verse bien el error en ciertos casos.
  • Evitar corrupción de datos cuando PHP genera salidas que no son de texto plano, por ejemplo al generar un PDF dinámicamente o imágenes (con php_gd2).
  • Al hacer peticiones por ajax, donde generalmente uno “no ve” lo que está llegando (con Firebug se puede ver), y por lo tanto tampoco se ve si la salida venía con errores entremedio.
  • En la misma linea de los 2 puntos anteriores, evita que se corrompa una salida en json o xml al hacer peticiones ajax que vengan con errores.

Por el lado del cliente, añade un filtro a Firebug para detectar estas cabeceras y desplegarlas en la Consola de Firebug.

Además, con un pequeño “hack”, se pueden redirigir TODOS los errores estándar que salen por pantalla, a las cabeceras, simplemente con un script (en PHP).

Hermoso, ¿y como lo hago funcionar?

Simple.

Seguir leyendo FirePHP, otra herramienta de depuración de PHP

Como guardar datos en una Cookie Segura (y un PHP FAIL)

Los últimos días los he dedicado al estudio de uno de esos viejos problemas que nunca había podido resolver. Consiste en el almacenamiento “seguro” de datos que viajan en un canal inseguro y se almacenan en un medio inseguro. Puntualmente, hablo de COOKIES. Cuando hablamos de protocolo HTTP(S), las cookies son el único “repositorio de datos” o almacenamiento persistente en el lado del cliente (navegador) con el que podemos trabajar. En las cookies, podemos guardar las preferencias de un usuario (por ejemplo, el idioma que escoja, la última página que vió, etc…). Y el problema puntual con cookies: guardar la identidad del usuario para “recordar” su sesión. El peligro esta en el como se guarda esta identidad. Lo bueno es que ya encontré un método que me convenció, y realmente es bastante “simple” como algoritmo. Lo que no fue simple fue la implementación. La verdad es que no se como pretendía completar el primer punto de mi roadmap (Lista de control de acceso o ACL) sin tener primero un método decente de autenticación. Al menos ya di con una respuesta.

Seguir leyendo Como guardar datos en una Cookie Segura (y un PHP FAIL)

Hackeando phpDocumentor

Uno de mis objetivos en torno al desarrollo web en general, es respetar lo más estrictamente posible los estándares W3C.

La documentación generada por phpDocumentor lamentablemente no es completamente limpia en ese sentido. Y como phpDocumentor es Software Libre, decidí meterle mano.

phpDocumentor tiene unas clases “Converter”, dedicadas a transformar la información analisada del código fuente en el formato de salida. Los 2 converters afectados son HTMLframesConverter.inc y HTMLSmartyConverter.inc.

frames hace la documentación en páginas HTML en marcos, y Smarty en una página completa por cada elemento documentado. Ambos usan smarty como motor de plantillas.

Fijándome en los errores descubiertos por Html Validator for Firefox y ZendStudio, logré identificar los archivos fuente afectados. En su mayoría eran errores tontos en las plantillas, como el uso de mayúsculas en las etiquetas y nombres de atributos, falta de atributos obligatorios y esas cosas. Pero hay unos detalles que no depende de los templates, sino de las clases Converter. Por ejemplo, me topé con que el árbol de clases queda con etiquetas de cierre </ul> y </li> sueltas. Tampoco se escapan los caracteres “&” de los parámetros pasados por referencia. Muchos otros lugares de las plantillas tienen problemas con etiquetas con contenido vacío (por ejemplo, me vi obligado a rellenar el tag @copyright en todos los archivos fuente y así evitar un <ul></ul>).

Ojeando el código, encontré que el método getRootTree() consiste en un algoritmo iterativo que recorre el arreglo de nodos de información de las clases. El problema es que los método iterativos que trabajan con arreglos o árboles, suelen requerir muchas más variables auxiliares, por lo cual confunde mucho. Además recuerdo haber trabajado en una clase que desplegaba listas HTML con <ul> y <li>, pero usando un método recursivo.

Para quien le interese el concepto, hay un patrón de diseño llamado “Composite”, que ocupa el mismo principio de recursividad, pero en el recorrido se hace entre objetos (cada nodo es propiedad de otro objeto de igual clase).

Como me fue imposible comprender el error, decidí derechamente reescribir el método del HTMLframesConverter.inc y HTMLSmartyConverter.inc (era idéntico). Además, tuve que quitar unas etiquetas de apertura<ul> y cierre </ul> en los métodos generateFormattedClassTrees() y generateFormattedInterfacesTrees() que invocaban a getRootTree().

Acá está uno de los archivos fuente modificados por mí, por si alguien le interesa: http://pastebin.com/f3c61b7c5

Por supuesto, mandé este tema al bug tracker y a la lista de correos de phpdocumentor. Espero que ojala se resuelvan los detalles pendientes. Por lo que he visto, últimamente están más concentrados en lo que será el soporte de PHP6.

phpDocumentor: como doxygen pero para PHP

Documentar el código es más que dejarlo bonito. Es hacerlo entendible.

“Comentar el código es como limpiar el cuarto de baño; nadie quiere hacerlo, pero el resultado es siempre una experiencia más agradable para uno mismo y sus invitados”
— Ryan Campbell

Uno de los propósitos iniciales de este blog, era combatir mi inquietante amnesia. No se ustedes, pero me es muy frecuente, que después de muchos días, semanas o meses sin ver el código que estaba trabajando, termino olvidando que hacía o como funcionaba.

“Ley de Alzheimer de la programación: si lees un código que escribiste hace más de dos semanas es como si lo vieras por primera vez”
— Via Dan Hurvitz

Hay solo una forma de combatirlo: documentando.

Será una lata, pero creo (seriamente) que los lenguajes de programación debieran mandar advertencias cuando no documentamos el código fuente.

Cuando estuve en inserto en el proyecto GDT, me topé de cerca con Doxygen, una excelente herramienta para documentar el código en función de etiquetas especiales insertas en los comentarios. Muchos años antes, me tocó conocer otra grandiosa herramienta, que ayer re-descubrí: phpdocumentor.

¿Que tiene de fantástico?

Tiene varios detalles que lo hacen un amor:

  • Esta escrito en PHP.
  • En su documentación incluye los tags especiales, con ejemplos, para escribir correctamente los comentarios.
  • Funciona por interfaz web y por consola. Posibilitando automatizar el proceso de documentación
  • Se puede configurar, guardando un archivo personalizado .ini con las opciones. Esto permite automatizar más aún el proceso.
  • Exporta a varios formatos, incluyendo HTML, PDF y CHM. Incluso tiene diversas plantillas para producir distintos estilos de HTML. También se pueden personalizar estas plantillas.

Sin duda debe tener más gracias, pero con eso es suficiente por ahora.

Ejemplos

Para probar, documenté TODAS las clases de Gonium y dejé copia acá. Sin ir más lejos, la documentación del API de Zend Framework está producida con phpDocumentor.

Sugerencia

Ser buen programador, no solo significa adoptar las mejores convenciones para escribir el código, usar el mejor IDE (esto es una estupidez, pero lo he escuchado), presumir el uso de patrones de diseño novedosos o presumir de código limpio y óptimo. Documentar es una tarea básica que DEBIERA SER OBLIGATORIA. No solo si sufres algún problema de memoria (con la de tu cabeza, no con la del PC) como yo.

Además es mucho más tedioso documentar un montón de clases ya escritas, que no sabes exactamente que hace, que comenzar documentando desde le principio. Si estas comenzando un proyecto, HAZLO YA, sino TAMBIN.

Caso personal

En Gonium hay algunas cuantas clases, que en su momento me pareció bueno crear mientras se me ocurría como implementarlas (por ahí por febrero de este año). Ahora no recuerdo que diablos quería hacer con ellas :B

Fuente de las citas: Variable not found: Otras 101 citas célebres del mundo de la informática.

PHP y Xdebug

Hace unas semanas encontré respuestas a preguntas que me planteé hace años acerca de PHP.

Unas de las primeras cosas que aprendemos cuando conocemos PHP, es que al trabajar en la web, el motor funciona con ciertos límites. Límite de tiempo de ejecución (30 segundos por omisión) y límites de uso de memoria (16M por omisión en mi caso).

Lo malo no es que existan límites, todo lo contrario, en el caso de una aplicación web, de naturaleza concurrente, es necesario que lo que hace un usuario no pase a llevar lo que hace otro, cuidando de pasada los recursos de la máquina servidora. Sería nefasto programar mal un ciclo, de tal modo que en ciertas condiciones se vuelva infinito y además la ejecución no parara nunca. También sería catastrófico que tan solo 2 usuarios ejecutando un script terminaran haciendo colapsar el servidor por uso excesivo de memoria. El problema está cuando estamos desarrollando y olvidamos estos límites, lamentablemente en las situaciones más incomodas es cuando se manifiestan, por ejemplo al extraer demasiados datos desde una base de datos, o al hacer una operación muy larga en uso de disco (por ejemplo copiar muchos archivos de un lado a otro), o al leer un archivo muy grande, etc…

Entonces las preguntas que me hice hace años fueron algo así:
¿Como puedo saber cuanto tiempo demora la ejecución de mi script? ¿Como puedo saber cuanto que funciones/procedimientos son las más lentas? ¿Como puedo saber cuanta memoria consume mi script en ciertas condiciones? ¿Como puedo saber cuanta memoria consume una operación?

RESPUESTA: Xdebug

Xdebug es una extensión para PHP (como la GD, BZip2, Mysql, …) pero funciona como una extensión algo especial.

Primero lo primero: Hacerla funcionar

En *Ubuntu afortunadamente se encuentra en los repositorios. También se encuentra en Debian Lenny con el mismo nombre:

sudo apt-get install php5-xdebug

También es conveniente que en este punto, instalemos las otras herramientas, si es que no están instaladas. Entre ellas, podemos además instalar kcachegring (advertencia para los gnomeros: kcachegrind por su K inicial, nos dice que ocupa librerías de KDE), una aplicación gráfica que nos sirve para ver los archivos cachegrind.out.* que genera el “profiler” de xdebug (si es que lo queremos ocupar). El paquete sysvconfig agrega el comando “service” que ayuda para acortar un poco las llamadas a los scripts de se control de servicios.

sudo apt-get install sysvconfig apache2 libapache2-mod-php5 php5-xdebug kcachegrind

Una vez instalado el servidor Apache, PHP, la extensión Xdebug y Kcachegrind

Debo confesar que intente instalarla en Windows Vista también, pero me fue imposible, el binario precompilado no funcionó ni a palos. Tal vez lo intente más adelante con XP virtualizado, o compilando la librería.

Configurar la extensión

Las versiones nuevas de PHP en Linux permiten tener archivos de configuracion ( *.ini ) separados. En *ubuntu existe la carpeta /etc/php5/apache2/conf.d

Luego de la instalación de xdebug, se crea un archivo /etc/php5/apache2/conf.d/xdebug.ini que simplemente carga la librería de la extensión.

En ese mismo archivo (si no es posible, puede agregar la configuración directamente al php.ini), podemos agregar las directivas para configurar el profiler y el depurador remoto:

Antes:

zend_extension=/usr/lib/php5/20060613+lfs/xdebug.so

Despues:

zend_extension=/usr/lib/php5/20060613+lfs/xdebug.so

xdebug.profiler_enable = On
xdebug.profiler_output_dir = /tmp
xdebug.profiler_output_name = cachegrind.out.%p

xdebug.remote_enable=true
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
xdebug.remote_handler=dbgp

Acá están las mismas opciones adicionales para el php.ini (o xdebug.ini).

Ok, esto hará que los archivos del profiler se guarden con en la carpeta /tmp con nombre cachegrind.out.%p donde %p es el número de proceso que está ejecutando PHP. Si se llamo desde el navegador web, correspondera al número de proceso de Apache. Además, si nuestro apache está corriendo como multihilo, el número corresponderá la hilo que procese el script con PHP.

¿Que se puede hacer con Xdebug?

Tiene varias características que facilitan el desarrollo, por ejemplo:

  • Reemplaza los mensajes de error predeterminados de PHP, por otros con mayores detalles, que además de mencionar el tipo de error y la linea donde ha ocurrido, incluyendo una traza con el anidamiento de las funciones llamadas, desde “{main}” hasta el punto donde ocurrió el error, donde además muestra el nombre de la cada función llamada, el “tiempo” en el que ocurrió y cuanta memoria se ha consumido hasta ese punto.

    Script de Ejemplo | Resultado:

  • Reemplaza algunas funciones naturales de PHP para dar mayor información. Por ejemplo la función var_dump() que nos muestra el tipo y contenido de un dato, ahora colorea de distinta manera cada tipo. También se puede configurar Xdebug para que solo muestre cierto nivel de anidamiento cuando queremos ver un array o un objeto, es decir, si un array tiene 10 dimensiones de profundidad, puedo configurarlo para mostrar hasta 3, para así facilitar la legibilidad. Es usual ocupar var_dump en varias partes mientras se desarrolla cuando no estamos seguros de que valor tiene una variable.

    Script de Ejemplo | Resultado:

  • Incorpora funciones nuevas, que permiten ver detalles antes desconocidos. Por ejemplo:
    • xdebug_time_index( ) Retorna un float con el valor del tiempo de ejecución desde “{main}”, es decir desde que comenzó a correr el script.
    • xdebug_memory_usage( ) Retorna un entero con el valor del uso de memoria actual.
    • xdebug_peak_memory_usage( ) Retorna el pick de memoria ocupada, es decir, el máximo (por supuesto, hasta antes de llamar la función).
    • xdebug_call_* Son varias funciones que retornan datos sobre “el lugar” donde se esta ejecutando algo. Por ejemplo, podemos introducir xdebug_call_class en una función para luego poder averiguar” desde que clase” se llamo a esa función, xdebug_call_line para saber en que linea y así… Más detalles en la documentación básica de xdebug.
  • Perfilar el código. Quienes hayan trabajador con C y otros lenguajes, tal vez conocen valgrind. Valgrind es una herramienta que sirve para perfilar un programa en C, compilado con opciones de depuración. De esta manera se puede hacer un análisis de rendimiento del programa. Xdebug puede generar archivos del mismo formato que valgrind, de tal modo que podemos verlo con cualquier herramienta compatible, como Kcachegrind.

    Script de Ejemplo | Resultado: (notece que no es un navegador sino Kcachegrind)

  • Integrar el depurador con un IDE: Es una característica que no he explotado a fondo, pero al igual que otros lenguajes como C, xdebug permite “ver” el funcionamiento del programa en tiempo real. Para ello implementa un protocolo común llamado dbgp (el mismo que se ocupa con C/C++ y otros lenguajes). La extensión actua como un servicio, y el IDE como un cliente (notence las líneas ocupadas para configurar en el xdebug.ini)

Más adelante, exploraré más características de xdebug, al menos con las que mostré acá, ya es suficiente para trabajar mejor.

To be continue…

Actualización: El día Jueves 26 de Junio del 2008 a las 22 horas, poco después de publicar este artículo, comenté acerca de PHP y Xdebug en el chat de irc.debianchile.cl => El log (registro) pueden verlo acá (gracias por invitar :D).