Aún más rendimiento con CssDispatcher

En el artículo “Maneja las CSS como un profesional” veíamos algunas técnicas para insertar variables y funciones en las hojas de estilo, así como posibles mejoras del rendimiento en el cliente a la hora de servir las CSS, y para ello utilizábamos la biblioteca CssDispatcher.

Pues bien, en este post vamos a ver varias soluciones para aumentar el rendimiento en el servidor cuando servimos hojas de estilos, especialmente si son hojas de estilos tratadas con CssDispatcher.

Es importante diferenciar las mejoras de rendimiento en el cliente y el servidor. Mientras los benchmarks nos dicen que el 80% del tiempo de carga de una página lo causa el cliente (transferencias, renderizado, etc), para nosotros también es importante ese otro 20%, porque genera una carga en el servidor (acceso a disco duro, procesador, memoria…) que puede ponernos en aprietos si las visitas aumentan.

Accesos al disco duro

De por sí, servir una hoja de estilos simple no suele ser muy costoso para un servidor web. Si un cliente solicita /main.css, el servidor abre el archivo, lo lee y lo devuelve. Además, si el sistema operativo implementa caché de ficheros, 1000 visitas no generarán 1000 accesos al disco duro, lo cual aumentará la velocidad y reducirá la carga del servidor.

Si queremos ir más allá y acelerar aún más los accesos a disco duro podemos poner los archivos del servidor un sistema de archivos montado sobre la memoria RAM. Es decir, una porción del sistema de archivos que, en lugar de guardarse en el disco duro, lo hace sobre una porción de la memoria RAM. No es una técnica muy recomendable, porque aunque no es difícil montarlo, los datos desaparecen al apagar o reiniciar la máquina, por lo que habría que tener sincronizados los directorios en memoria con otros en el disco duro para que no se perdiesen.

Procesamiento de la petición

Como ya he dicho antes y todo el mundo sabe, para el servidor web devolver un archivo estático no le cuesta más que abrirlo e irlo enviando por el socket. Pero si la hoja de estilos pasa por el compilador de PHP (por introducir códigos PHP en la hoja de estilos) entonces la cosa se complica un poco. Para acelerar el procesado de scripts es recomendable usar:

  • Una caché de salida, que evita tener que ejecutar repetitivamente el mismo código para cada petición.
  • Un opcode cache, que evita tener que compilar el código para cada petición (si hemos implementado caché de salida, para la mayoría de las peticiones no será necesario ni compilar ni ejecutar el código).

Diagramas de flujo para el despacho de peticiones con caché

Para la opcode cache existen herramientas como APC, XCache o eAccelerator, que una vez instaladas y configuradas debidamente funcionan sin que tengamos que modificar el código de nuestra aplicación web. Puedes leer más sobre opcode cache en PHP Accelerators.

En cuanto a la caché de salida, hay principalmente dos caminos a seguir: gestionar la caché desde el servidor web o desde PHP. La ventaja del primero es que, al no ejecutar código PHP es un poco más rápido. Esto se puede lograr con el módulo Apache mod_cache. La otra posibilidad, gestionarlo con PHP, nos da más flexibilidad y control sobre la solución. En concreto, podremos guardar la caché en el disco duro o en memoria, con gestores de caché como Memcached (mi preferido).

Caché con URL propia

Existe una tercera solución, y es utilizar una caché en disco duro sin procesar las peticiones por PHP. El funcionamiento es el siguiente: si tenemos una hoja de estilos generada con CssDispatcher en/estilos.css.php, podemos guardar la salida en un archivo y ponerlo accesible en/estilos.css. Al ser un archivo estático, se servirá tan rápido como una hoja de estilos normal. Este sistema tiene un problema, y es que si tenemos hojas de estilos específicas para navegadores, no resultará fácil servir una u otra de forma estática. La única solución aparente es utilizar redirecciones y estructuras condicionales en los ficheros de configuración de Apache.

Algo de código, por favor

Vamos a implementar tres sistemas de caché: uno con Memcached, otro en disco y otro en disco accesible directamente.

Cache en Memcache

<?php
 
include 'class.Css.php';
 
//Nombre del elemento en Memcache
$cache_name = 'moduleName_' . Css::getUserAgent();
//Tiempo de vida. Para archivos que no cambien mucho, poner valores altos
$cache_time = 3600*24; 
 
//Conexión a Memcache
$mc = new Memcache();
$mc->connect('localhost');
 
//Si la salida no está en caché, se genera y se almacena
if (!$out = $mc->get($cache_name)) {
 
    //Incluye la biblioteca CssDispatcher.
    //No se incluye si no es necesaria
    include 'class.CssDispatcher.php';
 
    $estilos = new CssDispatcher;
 
    //Crea una nueva hoja de estilos
    $general = new Css('example.css.php');
    //Asigna variables
    $general->background = '#eee';
    $general->border_color = 'red';
    $general->header_size = 2.1;
 
    //Crea otra hoja de estilos para navegadores WebKit
    $another = new Css('example2.css.php', Css::UA_WEBKIT);
    $another->bold = 'font-weight: bold';
 
    //Añade las hojas de estilo al dispatcher
    $estilos->add($general);
    $estilos->add($another);
 
    //Añade un aviso
    $out = '/* Generated by CssDispatcher ' . strftime('%c') . " */n"
        . $estilos->render(false, true, false, true);
 
    //Guarda la salida en Memcache
    $mc->set($cache_name, $out, null, $cache_time);
}
 
header("Content-Type: text/css");
echo $out;
die();
 
?>

Tiempo de ejecución (renovando la caché): 3.6480ms
Tiempo de ejecución (utilizando la caché): 0.6439ms

Caché en disco duro

Este script tendrá será más lento y pesado para la CPU que el anterior, pero no necesita de servicios adicionales como Memcached, imposibles de instalar en alojamientos compartidos.

<?php
 
include 'class.Css.php';
 
//Archivo de caché
$cache_name = 'cssCache/moduleName_' . Css::getUserAgent();
//Tiempo de vida, poner valores altos para archivos que no suelen cambiar
$cache_time = 30; 
 
if (file_exists($cache_name)) {
    if (date('U') - fileatime($cache_name) > $cache_time) {
        $regenerate = true;
    } else {
        $out = file_get_contents($cache_name);
    }
} else {
    $regenerate = true;
}
 
//Si la salida no está en caché, se regenera
if ($regenerate) {
 
    //Carga la biblioteca CssDispatcher
    include 'class.CssDispatcher.php';
 
    $estilos = new CssDispatcher;
 
    //Crea una nueva hoja de estilos
    $general = new Css('example.css.php');
    //Asigna variables
    $general->background = '#eee';
    $general->border_color = 'red';
    $general->header_size = 2.1;
 
    //Añade otra hoja de estilos para navegadores WebKit
    $another = new Css('example2.css.php', Css::UA_WEBKIT);
    $another->bold = 'font-weight: bold';
 
    //Añade las plantillas al dispatcher
    $estilos->add($general);
    $estilos->add($another);
 
    $out = '/* Generated by CssDispatcher ' . strftime('%c') . " */n"
        . $estilos->render(false, true, false, true);
 
    //Graba la salida en el fichero
    file_put_contents($cache_name, $out);
}
 
header("Content-Type: text/css");
echo $out;
die();
 
?>

Tiempo de ejecución (renovando caché): 1.290ms
Tiempo de ejecución (utilizando caché): 0.242ms

El último caso, una caché en ficheros accesibles públicamente, es más rápida y más ligera que la anterior, pero nos añade la tarea de actualizar la caché cuando nos interese, bien con una tarea programada (cron) o mediante algún otro mecanismo.

<?php
 
include 'class.Css.php';
include 'class.CssDispatcher.php';
 
//Generamos hojas de estilos para todos los navegadores
$navegadores = array(Css::UA_IE6, Css::UA_IE, Css::UA_GECKO, Css::UA_WEBKIT);
 
//Para cada navegador generamos la hoja de estilos correspondiente
foreach ($navegadores as $navegador) {
    //Archivo de caché
    $cache_name = 'cssCache/estilos_' . $navegador . '.css';
    //Tiempo de vida. Para archivos que no cambien mucho, poner valores altos
    $cache_time = 30; 
 
    $estilos = new CssDispatcher;
 
    //Crea una nueva hoja de estilos
    $general = new Css('example.css.php');
    //Asigna variables
    $general->background = '#eee';
    $general->border_color = 'red';
    $general->header_size = 2.1;
 
    //Añade las plantilla al dispatcher
    $estilos->add($general);
 
    //Hoja de estilos para WebKit
    //No vale utilizar la detección de navegador de CssDispatcher
    if ($navegador == Css::UA_WEBKIT) {
        $another = new Css('example2.css.php');
        $another->bold = 'font-weight: bold';
        $estilos->add($another);
    }
 
    $out = '/* Generated by CssDispatcher ' . strftime('%c') . " */n"
        . $estilos->render(false, true, false, true);
 
    //Graba la salida en el fichero
    file_put_contents($cache_name, $out);
}
 
echo "Caché de CSS actualizada";
 
?>

 

Tiempo de ejecución del actualizador de caché: 4.009ms
Tiempo de obtención de la hoja de estilos: 86ms (incluye la transmisión del fichero)

Ya que con este método no tenemos un sólo punto de entrada para las diferentes hojas de estilos, será necesario cargar una u otra CSS en función del navegador, a través de los artificios clásicos: comentarios condicionales o la cabecera User-Agent. Pero tendremos que hacerlo manualmente, ya que al usar ficheros estáticos no se ejecuta CssDispatcher. Por ejemplo, según el ejemplo, si el navegador es Firefox tendremos que invocarcssCache/estilos_20.css.

Por mi parte, es todo por hoy. ¿Conoces alguna otra técnica para aumentar el rendimiento al servir CSS? ¿Has probado a cachear la salida de CssDispatcher?

Linux es un buen entorno de programación en PHP

Siempre he apostado por el software libre, pero hasta hace no mucho usaba Windows, un sistema privativo, para desarrollar. No me convencían las herramientas de programación en PHP para Linux, ya que estaba muy contento con Notepad++ para escribir scripts y TortoiseSVN para trabajar con Subversion. Usaba un servidor WAMP y phpMyAdmin para administrar la base de datos.

Ahora, sobre Debian, trabajo con unas herramientas que no tienen nada que envidiar a las anteriores. Vayamos por partes.

Un editor de PHP para Linux

Si algo me faltaba en Notepad++ era un autocompletado de código potente (el de Notepad++ se basa solamente en las palabras del archivo actual) y la autodocumentación en línea (es decir, soporte de phpDoc). Tras darle una oportunidad a Eclipse/PDT, me he decidido definitivamente por NetBeans. Tiene integración con Subversion, phpDoc, XDebug y Firefox, y me parece más productivo que Eclipse. Una de las características que más me gusta es que tiene en cuenta la cláusula @return de los comentarios phpDoc de una función para entender el tipo de dato que devuelve:

NetBeans, un buen IDE para programar con PHP

No obstante, no he dejado de usar Notepad++, gracias a WINE. Lo utilizo para manejar archivos de diferentes codificaciones, procesar textos con expresiones regulares y escribir PHP cuando no me apetece iniciar NetBeans ;-)

Un cliente Subversion para Linux

Como ya he dicho, NetBeans tiene soporte nativo de Subversion. En otros casos, utilizo kdesvn y RapidSVN. Además, he aprendido el valioso placer del cliente svn por línea de comandos ;-) Por cierto, existe un cliente privativo aunque muy potente llamado SyncroSVN, disponible para Windows, Mac y Linux.

Un depurador de PHP para Linux

De nuevo NetBeans me soluciona la papeleta, pero también utilizo KCacheGrind, un excelente visor de volcados XDebug:

KCacheGrind, herramienta para visualizar volcados de XDebug

Cross-browser en Linux

Si algo abunda en GNU/Linux son los navegadores. Los de siempre, Firefox (con el maravilloso Firebug), Opera, Chrome y lynx (o links o elinks), además de Konqueror (que nadie usa). Para el malvado Internet Explorer utilizo una máquina virtual con Windows XP en la que dispongo de muchas versiones de IE, gracias a Internet Explorer Collection. Además, existen renderizadores de Internet Explorer on-line.

Internet Explorer

Instalar extensiones es más fácil en Linux

Los paquetes Apache+PHP para Windows suelen traer algunas extensiones, pero a la hora de instalar otras nuevas (tanto PECL como PEAR) los métodos varían, y las utilidades de línea de comandos no siempre funcionan.

En Linux muchas extensiones PECL y bibliotecas PEAR están disponibles a través de los repositorios.

Repositorio Debian con paquetes PHP

Además, el paquete de desarrollo php5-dev permite instalar compilando las extensiones de la forma más sencilla:

# pecl install nombre_de_la_extension

Y lo mismo para librerías PEAR:

# pear install nombre_de_la_biblioteca

Conclusión

Si aún trabajas con Windows, anímate a probar GNU/Linux con Ubuntu o la distribución que más te guste. En una hora habrás podido instalar todas las aplicaciones que necesitas para programar de forma productiva y cómoda con PHP. Si ya lo has hecho, ¿qué experiencia tienes? ¿utilizas alguna de las herramientas que he citado? Comentar es gratis ;-)

Maneja las CSS como un profesional

Una parte importante de cualquier aplicación o sitio web son los estilos CSS. Las hojas de estilos se suelen escribir aisladas de la aplicación, sus tecnologías y metodologías. Además, suelen ser servidos como archivos estáticos, de forma que no pasan por la base de datos ni el resto de la aplicación. Existen buenas prácticas relacionadas con la legibilidad y mantenibilidad de las hojas de estilos, pero pocas veces se opta por mezclar las CSS con las aplicaciones, entre otras cosas porque servirlos como ficheros estáticos es más rápido que procesarlos con PHP, y porque a menudo los diseñadores que escriben los estilos no conocen las tecnologías de programación.

No obstante, como se explica en “Supercharge Your CSS with PHP Under the Hood” y demuestran algunas aplicaciones como Plone o phpMyAdmin, mezclar las tecnologías de programación con el lenguaje de estilos CSS puede aportarnos más potencia y comodidad a la hora de escribir, mantener y aumentar el rendimiento de las stylesheets. Y por el mismo precio también te presentaré CssDispatcher, una biblioteca que te ayudará a hacer todo eso casi sin esfuerzo.

Variables y funciones en CSS

En programación, si vas a utilizar varias veces un dato, lo almacenas en una variable para manejarlo más cómodamente. El mismo principio podemos aplicar, por ejemplo, con los colores en una hoja de estilos. De este modo evitamos repetir (es decir, recordar o copiar-pegar) códigos hexadecimales. Por ejemplo, el siguiente estilo:

.paginacion { border: 1px solid red; }
.paginacion a { color: red; }

…quedaría de este modo:

.paginacion { border: 1px solid <?=$rojo ?>; }
.paginacion a { color: <?=$rojo ?>; }

Como ves, he utilizado las etiquetas cortas y el operador de impresión <?= en lugar de echo para abreviar. Establecer variables para colores facilita la tarea de crear esquemas de colores intercambiables (y más legibles):

body { color: <?=$color_texto ?>; }
a { color: <?=$color_enlace ?>; }
h1 { color: <?=$color_primario ?>; }

#divCentral { border: 1px solid <?=$color_primario ?>; }

Como ya he comentado, phpMyAdmin hace uso de esta técnica. Aquí tenemos un pequeño ejemplo:

th {
    font-weight:        bold;
    color:              <? echo $GLOBALS['cfg']['ThColor']; ?>;
    background:         <? echo $GLOBALS['cfg']['ThBackground']; ?>;
}

En este caso no se usa el operador = para imprimir, y sí echo. Es recomendable hacer lo mismo ya que en muchos servidores (sobre todo con las versiones más recientes de PHP) las etiquetas cortas están desactivadas.

Además de colores, puedes utilizar las variables para calcular medidas relativas. Por ejemplo, si tenemos un layout de 800px de ancho con dos columnas, una de 600px y otra de 200, podemos expresarlo con medidas relativas (%) para hacer más accesible nuestras hojas de estilo:

#columna1 { width: <?php echo ($ancho_columna1/800)*100 ?>%; }
#columna2 { width: <?php echo ($ancho_columna2/800)*100 ?>%; }

También podemos utilizar propiedades completas como variables:

h1 { <?php echo $negrita ?>; }

Donde $negrita valdría font-weight: bold.

Llegados a este punto, seguramente estés pensando “muy bonito, pero ¿dónde defino las variables?“. En el tutorial de NetTuts los ejemplos muestran las declaraciones de variables en el mismo fichero que las CSS, pero no creo que sea una buena práctica. phpMyAdmin tiene ficheros separados donde se definen los valores, aunque utilizar el array $_GLOBALS no es muy elegante, sobre todo si tu aplicación es orientada a objetos.

Como ya adelanté al comienzo, vamos a ver una biblioteca llamada CssDispatcher que facilita la gestión de CSS con PHP. Esta librería propone un método concreto de definir las variables de los estilos, de forma que se identifiquen fácilmente y además los nombres no causen conflictos con el resto de variables de la aplicación. Este método es sencillamente añadir las variables a una instancia de la clase Css a través del tipado dinámico:

$general = new Css('general.css.php');
$general-&gt;fondo = '#eee';
$general-&gt;color_borde = 'red';
$general-&gt;cabecera = 2.1;

Aunque las variables son introducidas en el objeto, al usarlas en la plantilla CSS sólamente tenemos que especificar su nombre, como variables “tradicionales”:

body { background: <?php echo $fondo ?>; }

De este modo podemos asignar variables a cuantas hojas de estilos queramos, sin que interfieran los nombres:

$general = new Css('general.css.php');
$general-&gt;altura_cabecera = '5em';
 
$ie_hacks = new Css('ie_hacks.css.php');
$ie_hacks-&gt;altura_cabecera = '5.1em';

Ah, por cierto, las variables también pueden ser de tipo función anónima. Por ejemplo…

$general-&gt;layout = function($proporcion) {
    return $proporcion / 800;
}

…que se podría aplicar de este modo:

.columna1 { width: &lt;?=$layout(100) ?&gt;em; }

Un último apunte sobre CSS “plantilladas”: te recomiendo que las nombres con extensión .css.php, como se ve en los ejemplos, o bien .css.tpl. Utilizar la extensión simple .css puede llevar a confusiones… pero es sólo un consejo.

Aumentando el rendimiento

Tanto si usamos variables en las CSS como si no, podemos mejorar el rendimiento si las procesamos con PHP, tanto en el servidor (tardamos menos en procesarlas) como en el cliente (le llegan antes).

Un ejemplo es el envío de varias hojas de estilo como un solo fichero. Mientras las buenas prácticas de CSS recomiendan separar las hojas de estilo por secciones o por navegadores (por ejemplo, ie-hacks.css, webkit.css, etc), las buenas prácticas de rendimiento nos aconsejan minimizar el número de peticiones HTTP. Así pues, ¿qué escogemos: mantenibilidad o rendimiento? Pues yo me quedo con las dos: escribamos las CSS en ficheros separados y juntémoslas a la hora de servirlas.

CssDispatcher nos permite hacerlo de una forma muy sencilla. Una vez que hemos creado instancias de la clase Css para cada hoja de estilo, las añadimos a un objeto CssDispatcher:

$general = new Css('ejemplo.css.php');
$general-&gt;fondo = '#eee';
 
$otra = new Css('example2.css.php');
$otra-&gt;negrita = 'font-weight: bold';
 
//Creamos un dispatcher
$estilos = new CssDispatcher;
 
//Añadimos las CSS al dispatcher
$estilos-&gt;add($general);
$estilos-&gt;add($otra);
 
$estilos-&gt;render();

Cross-browser

Otro de los problemas comunes cuando se escriben estilos es la compatibilidad entre navegadores. No todos renderizan las CSS de igual forma, así que es habitual escribir hojas de estilo con propiedades específicas para Internet Explorer, Safari/Chrome, etc. Dependiendo del que esté utilizando el usuario se envía una u otra.

Se han venido utilizado tres métodos diferentes para cargar hojas de estilos específicas:

  • Comentarios condicionales (sólo funcionan en IE): para añadir CSS específicas de Internet Explorer basta con envolver la línea de llamada (
    <link rel="stylesheet"...) con las directivas<!--[if IE 6]>y<![endif]-->.
  • JavaScript: una vez cargada la página, se ejecuta un script que comprueba el navegador y carga dinámicamente la hoja de estilos correspondiente. En consecuencia, los usuarios que no ejecuten JavaScript (por seguridad o por usar un navegador viejo/limitado) no podrán cargar hojas de estilo específicas.
  • En el servidor:: antes de enviar la página, el script que la genera comprueba la cabecera HTTP User-Agent y escribe las invocaciones correspondientes al generar HTML.

Elegiremos el último método por ser más seguro y compatible. Con CssDispatcher definir CSS específicas de navegador es tan fácil como añadir un segundo parámetro en el constructor de la clase Css:

//Enviará la hoja de estilos si el navegador del usuario es Internet Explorer 6
$ie_hacks = new Css('ie_hacks.css.php', Css::UA_IE6);

Puedes especificar las siguientes familias de navegadores: Internet Explorer 6 (Css::UA_IE6), Internet Explorer >6 (Css::UA_IE), Gecko (Css::UA_GECKO), WebKit (Css::UA_WEBKIT). También puedes utilizar los sinónimos UA_MOZILLA, UA_FIREFOX, UA_SAFARIy UA_CHROME respectivamente. Para más información puedes ver la referencia de CssDispatcher.

En resumen

Hemos visto varias técnicas que nos ayudan a manejar de forma más eficaz y eficiente las hojas de estilos. Puedes utilizar las que necesites, tanto si quieres hacerlo de forma manual como utilizando CssDispatcher (u otras bibliotecas, si las encuentras dímelo!). A saber:

  • Asignación de variables en espacios de nombres seguros.
  • Hojas de estilos específicas de un navegador.
  • Minimización del código CSS.
  • Unión de hojas de estilos para un envío único.

Rendimiento en el servidor con cache

No hay que olvidar que generar estilos con CssDispatcher provoca una carga en el servidor por los accesos a disco (para obtener las CSS y otro para obtener los scripts) y por el tiempo de compilación y ejecución. Por ello, una buena técnica para aumentar la velocidad y reducir sobremanera el throughput es cachear el resultado final de la ejecución de CssDispatcher. Para cachear la salida de un script existen varias técnicas:

  • Cache en el servidor web: la salida de una petición se almacena en memoria o disco y se sirve sin ejecutar nada de PHP. En Apache esto es posible con el módulo mod_cache y sus motores de almacenamiento, mod_disk_cache y mod_mem_cache.
  • Cache a través de PHP: esta técnica hace básicamente lo mismo que la anterior, pero en vez de estar gestionada por el servidor web se gestiona con scripts PHP. Por ello, aunque no es necesario compilar y ejecutar los scripts de CssDispatcher sí es necesario ejecutar el script de control de cache, por lo que esta solución no es tan buena como mod_cache. No obstante, en servidores compartidos y otros entornos de escaso control es una buena solución. Además, el script de control de cache se puede cachear con los sistemas de cache de bytecodes como APC o eAccelerator, aunque eso ya es un tema aparte.
Artículo relacionado

MagiSQL ha muerto

Hace cerca de un año que comencé un proyecto llamado MagiSQL, con el objetivo de crear una herramienta modular de gestión de bases de datos relacionales, compatible con múltiples sistemas de BBDD y con licencia libre, por supuesto.

Me he planteado muchas veces la viabilidad y utilidad del proyecto, ya que la competencia es muy dura (phpMyAdmin, pgAdmin, Oracle Enterprise Manager, etc etc etc) y exige reinventar la rueda en la mayoría de los módulos. Además, para que el proyecto fuese exitoso no sólo era necesario que me dejase los ojos durante muchas horas, sino que más programadores se sumasen al proyecto y desarrollasen módulos compatibles con los sistemas gestores de bases de datos, ya que yo no tengo tiempo ni medios para hacer MagiSQL compatible con Oracle, MS-SQL Server, PostgreSQL, MySQL y DB2, como está planteado en los objetivos del proyecto (de momento sólo funcionaba con MySQL). Además, este verano he reescrito por completo el núcleo, lo que ha retrasado y complicado aún más el desarrollo.

Por estos motivos y muchos otros (baja productividad, falta de tiempo y concentración, cuestiones personales…) he decidido no continuar el proyecto. Nunca ha alcanzado un nivel de madurez mínimo como para ser usable, y la gran parafernalia de módulos, clases y patrones hace bastante inútil el código que hay en mi disco duro y en el SVN de Sourceforge. En resumen, que se irá todo a la basura.

¿Todo? Eso significaría tiempo perdido, derrota, fracaso. Y aunque no deja de serlo, es un fracaso del que estoy orgulloso y del que he aprendido un montón, entre otras cosas:

  • He ideado el patrón de diseño “Application Status”, del que tendréis más noticias dentro de algún tiempo… ;-)
  • Me he acostumbrado a escribir documentación en línea (phpDoc) y en inglés.
  • Me he familiarizado con la biblioteca AdoDB.
  • Me he hartado de Smarty. Era el último proyecto en el que lo usaba, y desde ahora sólo utilizaré plantillas PHP.
  • He aprendido más cosas sobre la reescritura de URL y expresiones regulares.
  • He comprendido e implementado multitud de patrones.
  • Me he familiarizado con las excepciones de PHP y los métodos mágicos.
  • He explotado las novedades de PHP 5.3.
  • He encontrado un buen entorno de programación en PHP sobre Linux (Netbeans, KCacheGrind, etc).
  • Me he convencido una vez más de que reinventar la rueda es friki, divertido pero inútil y bastante frustrante.
  • He escuchado cientos de discos mientras hacía todo eso ;-)

Bueno ¿y ahora, qué? Ya que el proyecto era para una asignatura de la carrera (aprovecho para decir que, tras pasar al Grado en Informática en la UCAM, he tenido que volver a matricularme de una asignatura que ya tenía aprobada), será sustituido por un motor de almacenamiento en MySQL para Object Freezer. Object Freezer es una biblioteca escrita por Sebastian Bergmann para almacenar objetos en la base de datos CouchDB sin preocuparse de SQL, DAO y demás inventos del pasado ;-)

La licencia de PHP prohíbe nombrar a tus proyectos “PHPnosequé”

Navegando por la documentación de PHP, he ido a parar a la página de licencia. Es esta página, además del texto legal se dan algunas explicaciones e indicaciones, entre las cuales está la instrucción de no usar la denominación “PHP” en nombres de proyectos que utilicen esta tecnología.

De hecho, esta indicación viene apuntada en una de las cláusulas la propia licencia:

4. Products derived from this software may not be called “PHP”, nor

may “PHP” appear in their name, without prior written permission

from group@php.net. You may indicate that your software works in

conjunction with PHP by saying “Foo for PHP” instead of calling

it “PHP Foo” or “phpfoo”

Más claro agua. Así que proyectos como phpMyAdmin, CakePHP, PHP-Nuke y un interminable etcétera están inclumpliendo los términos de la licencia, a nos ser que cuenten con un permiso especial del grupo PHP (ignoro si es así).

Por supuesto, esto no significa que Rasmus Lerdorf y compañía tengan “patentada” la denominación PHP, sino que no puedes usarla en proyectos que se basen en su tecnología, ya que se consideran derivados de PHP. Una curiosa cláusula que sorprende que no hayan leído o no hayan atendido los responsables de tantos proyectos exitosos.