Extendiendo PHP (I)

Aunque la inmensa mayoría de las necesidades que plantea la programación en PHP se pueden resolver directamente con este lenguaje podemos encontrarnos con alguna necesidad muy especifica que nos obligue a extender las capacidades de PHP bien para agregar una nueva funcionalidad o bien para obtener un mayor rendimiento en determinadas partes del código.

Cualquiera que sea al necesidad también puede ser resuelta a través de PHP, creando una extensión. Empleando las herramientas proporcionadas por los desarrolladores de PHP y haciendo uso de su API en C podemos obtener lo que nos propongamos.

Existen dos tipos de extensiones: extensiones PHP y extensiones Zend. Las primeras proporcionan funciones o clases adicionales para el lenguaje (por ejemplo: GD, Ming etc) y las segundas son extensiones de bajo nivel que modifican el núcleo del lenguaje, como por ejemplo en los sistemas se cache por códigos de operación (APC, XCache, etc).

Para desarrollar una extensión en PHP necesitas una copia de código fuente de PHP y las herramientas de desarrollo para la programación en C. Lo primero lo puedes conseguir en www.php.net y lo segundo puede llegar en principio con gcc y gdb, compilador y depurador de GNU.

Otras herramientas necesarias, que tal vez ya tenga instalado tu sistema es

* autoconf: 2.13
* automake: 1.4+
* libtool: 1.4.x+ (except 1.4.2)
* bison: 1.28, 1.35, 1.75, 2.0 or higher
* flex: 2.5.4 (not higher)
* re2c: 0.9.11+ (0.12.0+ for HEAD)

Puedes emplear “apt-get install” para instalar todos estos paquetes si empleas distribuciones tipo debian.

Si no cumples casi ninguna de estos requerimientos te recomiendo que instales linux en tu máquina o cualquier otro sistema tipo UNIX. Y si no tienes ni la más remota idea de lo que estamos hablando deja de leer y sigue bajándote torrents de tus mp3s favoritos.

En el momento de escribir este artículo la última versión estable de PHP era la 5.2.9, quizás cuando leas estas líneas te parezca una versión anticuada pero esta noche es lo más reciente de PHP. Por supuesto la mejor forma de obtener el código más actualizado (y menos probado) es a través del repositorio público de PHP en http://cvs.php.net/.

Una vez que tengas el código de PHP lo mejor es que te familiarices mínimamente con su estructura y documentación. Lo segundo es preparar PHP en línea de comandos (CLI) para poder probar y depurar tu código rápidamente. Entra en el directorio de fuentes y ejecuta:

$ ./configure
$ make
# make install (como root)

Esto creará un binario ejecutable de php en /usr/local/bin. Si quieres tener disponible alguna extensión en este binario debes especificarlo al ejecutar configura pasándole la extensión que quieres tener como parámetro adicional; por ejemplo: –with-mysql=/usr –with-psgl –with-zlib para habilitar soporte para mysql, postgreSQL y zlib en el binario.

puedes verificar que todo ha ido bien ejecutando

$ php -v

Para generar el esqueleto de nuestra extensión debemos crear un fichero .def que defina la función que queremos agregar a nuestro php. Para continuar definamos la función que llamaremos dummy y que tendrá esta firma

string dummy(string $message,bool $inversion);

La función devolverá el mismo mensaje que se le envía como primer parámetro si el segundo parámetro es false y retornará la cadena invertida, con los caracteres en orden opuesto, si el segundo parámetro es true.

Nuestro fichero dummy.def podría contener lo siguiente

string dummy(string msg, bool invert) Devuelve la misma cadena enviada en orden normal o invertido

para generar el esqueleto de esta extensión debemos ejecutar lo siguiente si nos encontramos en la raíz del código fuente de php descargado

$ cd ext
$ vi dummy.def
(editamos el contenido del fichero)
$ ./ext_skel –extname=dummy –proto=dummy.def

El comando habrá creado un directorio dummy dentro de ext con los ficheros iniciales básicos para el funcionamiento de tu extensión, también te aparecerá un pequeño conjunto de instrucciones para compilar el código de tu extensión junto con php. Sin embargo ejecuta paso por paso estas instrucciones y ya tendrás tu primera extensión creada

$ cd .. (o ir a la raíz del código fuente de php descargado)
$ ./buildconf –force
$ ./configure –with-dummy
$ make

Para probarlo puedes ejecutar

$ ./sapi/cli/php -f ext/dummy/dummy.php

En la siguiente entrega entraremos en detalle de lo que acabamos de hacer y crearemos el código real para nuestra aplicación.

Ah! felicidades por haber creado tu primera extensión para PHP 😉

Puedes ver la segunda parte de este artículo aquí: Extendiendo PHP (II)

Trabajo colaborativo con git

Continuaremos con otro artículo sobre el gestor de versiones git. Esta vez nos centraremos en el trabajo colaborativo con git. Como crear nuestro repositorio a partir del creado por otras personas. Recordemos que git no utiliza un repositorio centralizado sino que cada desarrollador tiene un repositorio completamente funcional.

Lo primero es obtener un repositorio de otro desarrollador en una máquina local. Para ello basta ejecutar con dirigirnos al directorio donde queramos nuestro nuevo repositorio y a continuación ejecutar

$ git clone /ruta/al/repositorio directorio-nuevo-repositorio

ejemplo

$ git clone /home/novanebula/repo1 repo2

Suponiendo que /home/novanebula/repo1 contuviera el repositorio antiguo git crearía un nuevo directorio llamado repo2 que contiene el nuevo repositorio.

Podemos trabajar con normalidad sobre el nuevo repositorio. Cuando terminemos y estemos satisfechos con los cambios ejecutamos

$ git commit -a

Para llevar estos cambios al repositorio original debemos ir a ese repositorio o solicitar a la persona que lo lleve que ejecute desde el directorio de este repositorio:

$ git pull /ruta/nuevo/repositorio branch

ejemplo

$ git pull /home/novanebula/repo2 master

Y las modificaciones en el segundo repositorio se aplicarán al primero. Si este contenía modificaciones locales hay que resolver conflictos. Por lo tanto pull hace dos tareas trae las modificaciones de otro repositorio y mezcla estas modificaciones en el repositorio donde se ha ejecutado.

Si el usuario del primer repositorio quiere analizar las modificaciones que se han introducido en el segundo antes de ejecutar un pull. Puede hacerlo ejecutando

$ git fetch /home/novanebula/repo2 master
$ git log -p HEAD..FETCH_HEAD

Es posible definir dentro de un repositorio otros repositorios locales para simplificar las ordenes entre ellos:

(repo1)$ git remote add /home/novanebula/repo2 repo2

Ahora para recoger los cambios en el repo2 podemos ejecutar

(repo1)$ git fetch repo2

Analizar los cambios

(repo1)$ git log -p HEAD..FECH_HEAD

y mezclarlos en el repositorio actual con:

(repo1)$ git merge repo2/master

o con

(repo1)$ git pull . remotes/repo2/master

Además desde repo2 se puede mantener una copia actualizada de las modificaciones en repo1simplemente ejecutando

(repo2)$ git pull

Esta opción ya estaba disponible desde que repo2 fuera creado con el comando clone

(repo2)$ git config –get remote.origin.url

Git también mantiene una copia del repo original bajo el nombre origin/master:

(repo2)$ git branch -r

Si repo2 tuviera que trabajar desde otro servidor podría hacerlo a través del protocolo ssh ejecutando este clone:

$ git clone host-address:/home/novanebula/repo1 repo2

Git también tiene un protocolo nativo o puede usar rsync o http. Pudiendo trabajar incluso al estilo de CVS con un repositorio central sobre el que todos los desarrolladores enviasen sus cambios.

Estadisticas navegadores firefox, ie, chrome

A día de hoy estas son las proporciones de uso de navegadores de los visitantes de esta página. Lo que confirma la evolución general y los número que nos da w3c

Estadísticas navegadores

1. Firefox – 52.99%
2. Explorer – 35.83%
3. Chrome – 3.95%
4. Opera – 3.36%
5. Mozilla – 1.93%
6. Safari – 1.18%
7. Konqueror – 0.67%
8. HTC-8900 – 0.08%

Git, el sistema de control de versiones de Linux

Git es el sistema de control de versiones cuyo creador fue Linus Torvals. Aunque actualmente otras personas se dedican a la administración del desarrollo de la aplicación. Sus principales puntos fuertes son su gestión distribuida y su sencillez a la hora de gestionar y mezclar ramificaciones en el código

Para comenzar y tras instalar el paquete podemos introducir nuestro nombre y email

$ git config –global user.name “Nombre apellido”
$ git config –global user.email [email protected]

Para comenzar a versionar un proyecto bajo git debemos entrar en el directorio donde tengamos el código y ejecutar:

$ git init

Tras ejecutarlo se generará un directorio .git

El siguiente paso es tomar una instantanea del código que está actualmente en el proyecto

$ git add .

Ahora la instantánea es almacenada en un área reservada. Puedes almacenar permanentemente el contenido del proyecto ejecutando

$ git commit

Te pedirá que insertes un comentario para este cambio en el código del repositorio.

Para ver los cambios que has introducido en el código con respecto a lo que hay en el repositorio se puede ejecutar

$ git diff –cached

También puedes ejecutar
$ git status

Para obtener una breve descripción de la situación actual

Existen otros comandos útiles como por ejemplo:

$ git commit -a (detecta modificaciones en ficheros, pero no ficheros nuevos y los comitea)
$ git log (historial cambios)
$ git branch nombre-nueva-rama (crear una nueva rama de desarrollo)
$ git branch (lista de ramas)
$ git checkout nombre-rama (entrar en rama nombre-rama)
$ git merge nombre-rama (mezcla la rama nombre-rama con la rama master)
$ git branch -d nombre-rama (elimina la rama nombre-rama asegurandose que los cambios están en la rama actual)
$ git branch -D nombre-rama (eliminación rama nombre-rama)
$ gitk (representación gráfica del historial del repositorio)

$ git clone ruta-repositorio nuevo-repositorio-clonado (crea un clon de un repositorio)
$ git pull ruta-repositorio-clonado rama (mezcla los cambios del repositorio clonado)
$ git fetch ruta-repositorio-clonado rama (ver los cambios antes de hacer la mezcla de código)

Pruebas unitarias con phpunit

Hoy el día el desarrollo del software involucra más y más tareas no directamente relacionadas con el desarrollo de código para el producto final sino también con todo el ciclo evolutivo para gestionar este desarrollo.

Una de las tareas más importantes involucradas en la gestión de este código son las pruebas sobre el código generado. Según el modelo de desarrollo de software empleado estas pruebas pueden jugar un papel más o menos central, pero siempre importante. Los dos tipos de pruebas más empleados son los test funcionales y las pruebas unitarias. En los test funcionales se evalúa la aplicación como un todo y se comprueba que se alcanzan unos determinados resultados tras realizar una serie de acciones sobre la aplicación. En las pruebas unitarias al contrario se analiza una porción de código que pueda ser analizada de manera aislada, como por ejemplo funciones y métodos. A los que después de pasarle unos parámetros de entrada debemos obtener otros parámetros de salida claramente definidos.

Ambos tipos de pruebas pueden servir a muchos niveles en el ciclo evolutivo de la aplicación: documentación, pruebas de regresión, análisis de bugs etc

Vamos a comentar brevemente el uso de PHPUnit para el desarrollo de pruebas unitarias en PHP

PHPUnit es un paquete que podemos encontrar en PEAR, para instalarlo desde una máquina debian/ubuntu ejecutamos como root:

# apt-get update
# apt-get install php-pear

(pear instalado)

# pear upgrade pear

(actualizar a las últimas versiones de pear)

# pear channel-discover pear.phpunit.de
# pear install phpunit/PHPUnit

(phpunit instalado)

Generalmente PEAR se instalará en /usr/share/php y si has instalado PHPUnit con las líneas de antes deberías poder ver un directorio llamado precisamente PHPUnit dentro de este directorio con las fuentes de PHPUnit.

Hay que recordar que por defecto php incluye el directorio de PEAR dentro del “path” de rutas donde debe buscar ficheros a incluir con requieres o includes. Así que para incluir la librería de PHPUnit dentro de tus scripts en php basta con poner

require_once ‘PHPUnit/Framework.php’;

Ejemplo:

<?php
require_once ‘PHPUnit/Framework.php’;

class ArrayTest extends PHPUnit_Framework_TestCase
{
public function testNewArrayIsEmpty()
{
// Create the Array fixture.
$fixture = array();

// Assert that the size of the Array fixture is 0.
$this->assertEquals(0, sizeof($fixture));
}

public function testArrayContainsAnElement()
{
// Create the Array fixture.
$fixture = array();

// Add an element to the Array fixture.
$fixture[] = ‘Element’;

// Assert that the size of the Array fixture is 1.
$this->assertEquals(1, sizeof($fixture));
}
}
?>

Para ejecutar las pruebas de esta clase debemos ejecutar

$ phpunit ArrayTest.php

Si hemos grabado el script anterior con este nombre (ArrayTest.php) en el directorio actual.

phpunit es un script php que se instala con PHPUnit. Su función es buscar y ejecutar las pruebas que tengamos definidas en el fichero que le pasamos como argumento. Finalmente devolverá un informe sobre el estado de las pruebas y los errores que se ha ido encontrando. Lo aconsejable es tener preparadas incluso antes de empezar a desarrollar métodos o funciones, pruebas sobre estos y a medida que se vaya probando el código o solventando bugs en el código (incluso antes de corregir el problema) ir generando pruebas adicionales sobre las distintas partes del código. Antes de enviar nada a producción deberemos ejecutar todas las pruebas.

La realización de pruebas unitarias es mucho más compleja de lo que se presenta aquí pero este es un buen punto de partida para ir cogiendo la costumbre de realizar este tipo de tareas en proyectos más o menos críticos.