Introducción a Ágora

Un poco de historia

Hace unos años descubrí un marco de desarrollo para PHP llamado CodeIgniter.  Es un marco estupendo, potente y que te evita bastantes dolores de cabeza, sin embargo lo encontraba grande y engorroso para algunas cosas, como por ejemplo mi página personal.  Por eso dediqué un tiempo a desarrollar mi propio marco basándome en los mismos principios de CI pero mucho más simple, al que llamé Ágora.

Según fui utilizándolo me di cuenta de que este nuevo marco, a pesar de ser más simple, seguía siendo demasiado engorroso y no era tan fácil de usar como yo pretendía, por lo que decidí hacer uno completamente nuevo.  Este nuevo Ágora fue una reescritura de aquel primero, que llegó hasta la versión 1.3.  Lo reduje a la mínima expresión:  un único archivo que define una única clase, pero conteniendo algunos módulos en un directorio aparte.  Tras realizar varios trabajos y corregir algunos errores, en la versión 2.2 eliminé estos módulos extra que pasaron a formar parte de otro proyecto aún por publicar, de forma que Ágora está formado por un único archivo: agora.php.  Hasta ahora Ágora estaba escrito para ser compatible con PHP 5, pero esa versión de PHP está ya más que superada, así que la versión 3.0 es un rediseño usando más cracterísticas de PHP 8 sin perder el espíritu original.  También he aprovechado para redefinir el API para seguir una nomenclatura más similar a la recomendada por PHP.

El nombre proviene de las plazas públicas de las antiguas polis griegas, las cuales eran los centros culturales, comerciales y políticos.  Actualmente Internet también cumple esta función, así que me pareció un nombre apropiado para el proyecto.

La idea

La idea principal detrás de Ágora es la sencillez.  En concreto he intentado seguir un concepto llamado KISS (siglas en inglés de mantenlo sencillo, idiota), según el cual se busca siempre la forma más simple y directa de solucionar un problema.

Para empezar hay que simplificar el propio problema.  También hay que evitar los "por si acaso" que tienden a complicar los algoritmos o a añadir funciones por si acaso son necesarios en un futuro.  En el caso de Ágora se han desechado muchas características que se suponen implícitas en las bibliotecas y paquetes PHP, como son el soporte a múltiples idiomas o conexión con bases de datos.  Existen bibliotecas disponibles y sobradamente comprobadas para la mayor parte de estas necesidades, que además son compatibles con Ágora, por lo que no hay de qué preocuparse.

Otro detalle a tener en cuenta es quién va a utilizar Ágora.  La mayor parte de las veces se diseñan este tipo de herramientas de forma que puedan ser utilizadas por gente con poca experiencia.  Sin embargo, al diseñar Ágora he supuesto que quienes van a utilizarlo tendrán experiencia, o que al menos pretenden llegar a tenerla.

También tuve en cuenta la libertad del programador.  Ágora no pone muchas restricciones a la hora de ser utilizado; simplemente pone a su disposición una serie de métodos, los cuales pueden llamarse de diferentes formas, sin forzar el ser utilizados de una forma determinada.  Además se pueden utilizar muchas otras bibliotecas junto con Ágora sin que haya problemas ni conflictos.

Otro tema importante es la documentación.  Es evidente que una documentación deficiente impide el correcto uso de cualquier cosa.  Como estoy acostumbrado a escribir comentarios en el código al tiempo que escribo este, sólo he tenido que esforzarme un poco más para asegurarme de que hasta el minimo detalle quedara explicado.  Si se necesita saber algo, basta con abrir el archivo fuente y leerlo.

El archivo agora.php

Ágora se compone de un único archivo: agora.php.  Todo, incluyendo la configuración del propio Ágora, está ahí.  Por lo tanto, no tiene más que incluir este archivo.

El contenido se divide en dos partes: la configuración y la clase Agora, la cual es Ágora en sí misma.  El archivo también contiene una clase adicional usada internamente por Ágora para ayudar a gestionar los módulos.

Configuración de Ágora

En las primeras líneas del archivo se definen unas pocas constantes de información y otras más que influyen en el funcionamiento de Ágora:

AG_VERSION
Una cadena que identifica el número de versión de Ágora.
AG_DIR
Contiene la ruta base.  Por defecto es el directorio donde se encuentra el archivo agora.php.
AG_DIR_VISTAS
Define la ruta donde Ágora buscará las vistas.  Por defecto está definida como un subdirectorio de AG_DIR llamado "vistas".
AG_DIR_MODULOS
Define la ruta donde Ágora buscará los módulos.  Por defecto está definida como un subdirectorio de AG_DIR llamado "modulos".
AG_VISTA_404, AG_VISTA_ERROR
Nombres de las vistas utilizadas por los métodos de gestión de error para generar la página informativa correspondiente.  Estos se encontrarán en el directorio de vistas y, por defecto, se llaman error404 y error.

Si desea cambiar las rutas o los nombres de las vistas de las páginas de error sólo tiene que definir estas antes de incluir el archivo agora.php, o cambiar las definiciones en el propio archivo.  Recuerde que las rutas han de terminar con la barra de separación de directorios o Ágora no funcionará correctamente.  Por ejemplo, si guardamos las vistas en un subdirectorio diferente al que define Ágora por defecto, podemos hacer lo siguiente:


<?php
# Ruta donde se encuentran las vistas.
  define (AG_DIR_VISTAS, 'plantillas/');
# Ahora cargamos Ágora.
  require 'php/agora.php';

(...)
    

Así, cuando Ágora deba cargar una vista, la buscará en el directorio php/plantillas/ en lugar de en php/vistas/, que es el que usaría por defecto.

La clase Agora

La clase Agora es una clase estática, lo que hace que su uso sea muy flexible.  Dado que todos los métodos de Agora son estáticos, se puede utilizar de tres formas distintas:

  1. Llamándo diréctamente a los métodos, a través del operador ::.  Por ejemplo: echo Agora::filtroXSS ($resultado);.
  2. Creando un objeto.  Por ejemplo: $a = new Agora (); y después: echo $a->filtroXSS ($resultado);.
  3. Extendiendo la clase en otra: class MiClase extends Agora { ... }

En general creo que todas las funciones de la case son autoexplicativas, por lo que leer los comentarios y definciones en el archivo agora.php debería bastar.  Reconozco que algunas partes son algo confusas, así que las detallo en la sección La clase Agora.  De todas formas recomiendo encarecidamente leer los comentarios del código fuente.

Gestión de errores y excepciones

He procurado que Ágora sea capaz de manejar todos los errores y excepciones que fueran posible.  Ágora lo gestiona de dos formas diferentes:

  • Devolviendo un valor por defecto que normalmente es el valor booleano false, aunque algunos métodos permiten definir este a través de uno de los parámetros.  Este método es el utilizado cuando la condición de error depende del contexto, es decir, del uso que se dará al valor devuelto.
  • Lanzando una excepción.  Cuando se lanza una excepción, no suele caber duda de que se trata de un error y rara vez depende del contexto.

En cualquier caso, recomiendo usar al menos una estructura try ... catch ... que englobe todo el código PHP, de forma que se esté seguro de que las excepciones serán mostradas adecuadamente al cliente (incluso las no lanzadas por Ágora).  De otra forma este recibirá un mensaje de error confuso y difícilmente interpretable por alguien sin conocimientos de PHP.  Yo suelo incluir una estructura similar a la siguiente en todas mis páginas:


<?php

  try {
# Aquí el código.
  }
  catch (Exception $Error) {
    echo "<p><strong>Se capturó una excepción:</strong><br />{$Error->getMessage ()}</p>";
  }
    

El ejemplo

En el subdirectorio html, además del archivo agora.php, se incluye un ejemplo.  Este está formado por el archivo index.php, que es el que representa el documento a generar, y unos pocos archivos de apoyo.  El archivo index.php está profusamente comentado explicando el funcionamiento de cada parte.

Notas

Se denomina clase estática a aquella que contiene, al menos, un método o propiedad de tipo static.
Las excepciones no son necesariamente errores, sino que pueden tratarse de situaciones que no son un error per se sino que dependen del contexto.  Por ejemplo, que no exista un elemento en una lista puede ser un error (si se trata de una mala definición) o, simplemente, puede significar que se debe usar el valor por defecto.