¡Salta! tm
Feed Estás viendo el archivo de la fecha: Octubre 2008
El caché de consultas SQL II

Ya me he quedado un poco más tranquilo con el asunto del caché de consultas SQL de que hablé en la anterior entrada. Después de otras cuentas vueltas, llego a la conclusión de que no sería bien desactivar el caché en la propia clase "GbDb" de Gesbit (como había propuesto y hecho antes) sino en la clase "Admin", y, en general, en el caso de borrar varios objetos de la base de datos al mismo tiempo. ¿Por qué no aplicarlo en la clase "GbDb"? Porque si borro una categoría de entradas no se da el problema del caché, únicamente se da si borro más de una categoría.

¿Y dónde sé que voy a borrar más de una categoría? En la clase "Admin", concretamente, en el método dedicado a ese menester: ahí sé si voy a borrar una o más categorías. Sin embargo, todavía cabría pensar que claro, a toro pasado... como sé que ahí se produce el problema, pues ahí pongo el parche, pero, ¿y si se da en otras circunstancias? Es lo que comentaba en la entrada anterior. Y, sin embargo, he decidido de momento desactivar el caché de consultas SQL ahí, precisamente, en los métodos de la clase "Admin" dedicados a llevar a cabo tareas sobre varios objetos a la vez.

Hacerlo así, quiere decir que, si alguna vez termina de ponerse en marcha el API de Gesbit, y este permite borrar varias categorías de entradas, por ejemplo, digo, en este caso, tocaría hacer exactamente lo mismo que en la clase "Admin": deshabilitar el caché de consultas SQL. Pero sigo viendo esta solución como la mejor, que se me ocurra ahora mismo. Quitar del medio el caché de consultas no es una buena idea: en primer lugar porque ya se hace uso del mismo (lo he comprobado) en algunas páginas de las bitácoras, y, en segundo lugar, porque todavía puede usarse más.

Deshabilitarlo para todos los "scripts" de administración tampoco parece una buena idea, teniendo en cuenta que los posibles problemas se presentan en situaciones muy concretas. Así que, de momento, creo que me voy a quedar tranquilo tal como dejo las cosas. Y a procurar en adelante, cuando se trabaje con la base de datos, y, sobre todo, cuando se borren registros de la misma, digo, procurar tener en cuenta el caché de consultas SQL. Joroba, que no estamos hablando de que un determinado tema sea más o menos bonito: estamos hablando de la integridad de la base de datos, ni más ni menos.

Iconos de agregadores Menéame Del.icio.us Digg Technorati Blinklist
Categorías: Desarrollo
El caché de consultas SQL

Hoy, casualmente, he descubierto un par de errores importantes en Gesbit, de los que menos me gustan, porque tienen que ver con la integridad de la base de datos. El segundo error lo consideraría grave, puesto que Gesbit puede dejar "sin listar" un enlace existente en la base de datos, pero, cuya categoría se desconozca. Y es que ambos errores (uno me llevó al otro) tienen que ver con el borrado de las categorías de entradas y enlaces, aunque, en el caso de las entradas, estas siguen mostrándose, aun sin que estén asociadas a categoría alguna.

Pero, el problema es que deben estar asociadas al menos a una categoría: la categoría principal o predeterminada, y así está "pensado" en Gesbit, es decir, cuando se borra una categoría de entradas, se comprueba si dichas entradas se quedan "sin categoría", y, de ser así, Gesbit se encarga de asignar a estas entradas la categoría predeterminada. ¿Dónde estaba el problema? Al borrar varias categorías de una vez, cosa que es posible, empero, entraban en juego el caché de consultas SQL, y, como alguna otra vez en el pasado, no tenía que hacerlo.

El asunto se las trae, porque, primero me ha costado llegar a la conclusión de que lo que fallaba era el caché de consultas SQL, es decir, se estaba "cachando" alguna consulta que no debía, y, por decirlo así, no podía completarse el proceso del borrado de las categorías correctamente. Vale. De acuerdo. Lo que falla es el caché. Ahora, ¿dónde establezco que no se use el caché de consultas SQL cuando se pretenda borrar una categoría de entradas? ¿En el "script" del panel de administración correspondiente? ¿Pero y si se quiere borrar una entrada desde fuera del "script", como pudiera ser, en un futuro, usando el API de Gesbit?

Total, que no queda nada claro dónde especificar que no se use el caché de consultas SQL en este caso. ¿Será mejor hacerlo en la propia clase "GbDb"? ¿Pero dónde? No puede hacerse alegremente, porque, por ejemplo, podemos identificar qué consulta exactamente no debe guardarse, pero, esta consulta puede usarse también en otras tareas, no sólo para borrar una determinada categoría de entrada, así que, ¿dónde se sitúa el "Set Caché Queries Off"? De moment, y, para salir del paso, lo he situado en el propio método que inicia el proceso para borrar categorías, tanto de entradas como de enlaces, en la clase "GbDb".

Pero, no me quedo satisfecho. En primer lugar, porque, ¿quién dice que no existen otros errores similares pero que todavía no se han encontrado, simplemente? Hay que tener en cuenta que yo he descubierto el error con las entradas de categorías por casualidad, y que he deducido que pasaría lo mismo con las categorías de enlaces, como así he podido comprobar. Entonces, ¿quién dice que no hay más errores de este mismo tipo pero que todavía no han aparecido? Me parece tan grave esto, que, una de las posibles soluciones que me he planteado ha sido la de prescindir del caché de consultas SQL.

Sobre todo, cuando he querido ver cuántas consultas SQL se estaban "cacheando" en mi bitácora personal, donde además uso varios plugins, y he comprobado que no se estaba "cacheando" ninguna consulta, es decir, que daría igual usar el caché o no usarlo. Pero, claro está, ¿hace esto inútil al caché de consultas SQL? Nada de eso. ¿¡Para qué lo implementamos sino!? El caché de consultas SQL es útil, desde luego, o puede serlo, en la composición de temas y para el trabajo de plugins, así pues, prescindir del mismo no parece una buena idea. Y, sin embargo, el mismo también está causando problemas: es un arma de doble filo, como suele decirse.

Así que no sé qué hacer. Claro, ahora mismo los errores que he referido en esta entrada están arreglados, o quedan arreglados, deshabilitando el caché de consultas SQL en sendos métodos de la clase "GbDb", pero, de verdad que no me queda nada claro tener que hacerlo así. Como no quiero alargarme demasiado lo dejaré aquí, recomendando actualizar a los pocos usuarios que estén utilizando Gesbit, y, si a ti que lees esto se te ocurre alguna cosa sobre lo dicho, te agradecería que la comentaras por aquí, a ver si entre todos podemos aclarar algo más este asunto. ;-)

Actualización: Ver esta otra entrada.

Iconos de agregadores Menéame Del.icio.us Digg Technorati Blinklist
Categorías: Desarrollo
Autocarga de clases para plugins

Hace pocas entradas lo comentaba: estaba buscando las vueltas para que los plugins no necesitasen requerir o incluir clases PHP por su cuenta. Después de echar un vistazo a cierta biblioteca para PHP que podría serme útil para cierto plugin, precismante, me percaté de que algo así sería realmente útil. No diré sino que dicha biblioteca cuenta con su propia función "autoload": porque estamos hablando de decenas de clases.

Para utilizar dicha biblioteca en un plugin para Gesbit, por lo tanto, sería preciso hacer unas cuentas decenas de "require" en PHP, para incluir cada una de las clases que, acaso, no iban a utilizarse después. Así que, había que hacer algo, y he dado unas cuentas vueltas al asunto en estos días, hasta hoy, que me he puesto un poco más en serio con ello y he conseguido una implementación a mi manera de ver bastante digna.

Pero, he tenido que equivocarme un par de veces para llegar a la solución que al final he adoptado. Tengo que decir que un primer momento me he liado bastante, porque mi objetivo era conseguir que los plugins pudiera añadir directorios donde buscar clases "a demanda". Es decir, incluir una acción que permitiera a los plugins especificar ciertos directorios donde Gesbit habría de buscar clases cuando fueran necesarias.

Pero, esta implementación me ha parecido un tanto rebuscada, y, en la práctica no era nada sencilla y complicaba las cosas tal vez demasiado. Así que, aunque sin descartar una solución parecida, he optado por simplificar, de modo que además no tuviera que realizar prácticamente cambios en Gesbit. Lo que he hecho ha sido añadir una función al archivo "gb-autoload.php", precisamente, donde se encuentra la función "__autoload" de PHP para Gesbit.

Dicha función es llamada únicamente una vez, precisamente, desde la propia función "__autoload", y lo que hace es reunir los directorios "originales" donde buscar clases (que ya se usaban antes de estos cambios) junto con los directorios "pscripts" de los plugins instalados (ojo, acaso no activados) disponibles en la instalación de Gesbit. Efectivamente, los plugins cuentan con una serie de directorios "predeterminados" y uno de ellos es "pscripts".

Esto pretende hacer la vida más fácil al autor de plugins, puesto que sus plugins, que son clases hijas de la clase "GbPlugin", cuentan con métodos, como por ejemplo, uno que retorna la ruta absoluta al directorio "pscripts" o su URL. Lo mismo vale para directorios como "jscripts", "images" y "styles". Pues bien, a partir de ahora los plugins pueden situar las clases de PHP que necesiten en el directorio "pscripts", y Gesbit las "autocargará" como el resto de clases, cuando sean necesarias.

Sin embargo no está todo dicho, porque el autor del plugin deberá tener alguna cosa en cuenta todavía: se sigue la misma convención que en Gesbit, debe haber una clase por archivo, y el nombre del archivo será el nombre de la clase más la extensión ".class.php". Si además en el directorio se encuentra un archivo "nombre de la clase" más la extensión ".const.php", también será incluido: exactamente igual que se hace en Gesbit.

Dos plugins se están beneficiando ya de este nuevo "sistema", como lo son los plugins "GbDefensio" y "GbTextile" para Gesbit. El "inconveniente" vendría dado (según lo veo ahora) porque hay que seguir las mencionadas convenciones para que "todo funcione", pero, en todo caso, ya podría hacer uso de la biblioteca de que hablaba al principio sin necesidad de hacer decenas de "requires" o "includes".

Quiero decir con esto último que acaso con dejar a los plugins "añadir" sus propios directorios se ganaría en algo, pero, lo que está claro es que también se sumaría cierta complejidad que tal vez merezca la pena ahorrarse en este caso, precisamente. Todo se andará, pero, creo que de momento, con una sola nueva función en Gesbit (y algunos cambios menores) se ha logrado no poco y bastante práctico, creo yo.

Iconos de agregadores Menéame Del.icio.us Digg Technorati Blinklist
Categorías: Desarrollo
Más AJAX en la administración

En el panel de administración de Gesbit no se hace un uso excesivo de AJAX, es decir, por ejemplo, para cambiar el estado de privacidad de una determinada entrada, desde el formulario de gestión de entradas, hay que "seleccionarla" y ejecutar la correspondiente "tarea". Y esto vale para una entrada o para varias a la vez, si se quiere. Otra posibilidad es editar la entrada, directamente.

He añadido un poco más de AJAX al panel de administración de Gesbit, y, me ha costado hacerlo, no creas. No que haya sido complicado, pero, que me ha costado decidirme a hacerlo o no. Ahora es posible editar "in situ" todas las propiedades de entradas, páginas, comentarios y enlaces. Como digo, no ha sido complicado de implementar, empero, no ha sido esto lo que me ha hecho dudar.

Porque, vamos a ver, está claro que poder cambiar el estado de privacidad de una entrada "con un clic" (en lugar de con un par de ellos) puede resultar útil, empero, siendo posible hacerlo, como digo, con un par de clic... ¿hasta qué punto merece la pena "complicar las cosas"? Básicamente se trata de complicar el código XHTML de los "scripts" en cuestión, si bien no excesivamente.

Además de lo dicho, ¿cada cuánto tiempo necesitas cambiar el estado de privacidad de una entrada? Tengo la sensación de que una bitácora puede ser algo lo suficientemente serio como para tomarse las cosas con más calma. Así, no me importaría tener que editar una entrada sólo para hacerla "privada", porque no es una cosa que se deba tomar a la ligera. Sin embargo,... ahí están los cambios.

Alguna vez he escrito aquí mismo que no pensaba añadir características en Gesbit que no fueran realmente necesarias. Y por eso cuando hago este tipo de añadidos me lo pienso más de una vez y más de dos. Y aún así hay veces que, dado por "terminado" el asunto, implementados los cambios, todavía me queda por saber si he hecho lo correcto o no. Creo que en este caso he acertado.

He acertado porque en realidad no se ha añadido nada a los formularios del panel de administración. Simplemente, donde antes se mostraba un "sí" o un "no" (para indicar si una entrada estaba publicada o no, por ejemplo) ahora se muestra el mismo "sí" o "no", salvo que este es un enlace, que, puede usarse para cambiar el valor de esa misma propiedad. Pero no hay ningún otro misterio, el asunto no va más allá (ni más acá).

Y tampoco se "rompe" con el sistema actual. Quiero decir, la "lista de tareas" que pueden aplicarse sobre entradas, páginas, comentarios, etc., sigue siendo perfectamente válida. Tal vez ya no para ejecutar una tarea sobre una sola entrada, pero, sí para hacerlo sobre varias entradas al mismo tiempo. Además, las tareas no se reducen sólo a cambiar ciertas propiedades de una entrada, por ejemplo, tambiém es posible hacer cosas como exportar una o varias entradas.

En fin, ya lo sabes: ahora es posible cambiar las propiedades "booleanas" de entradas, páginas, comentarios y enlaces, directamente, "in situ", gracias a "AJAX", en el panel de administración de Gesbit. Si quieres, puedes verlo ahora mismo en la demostración de Gesbit. Por lo demás, notarás también algún otro cambio en las "tablas" de los formularios, ahora con algunos elementos "centrados". ;-)

Iconos de agregadores Menéame Del.icio.us Digg Technorati Blinklist
Categorías: Desarrollo
Autocompletado de etiquetas en Gesbit

Captura del autocompletado de etiquetas en Gesbit Hace tiempo estuve buscando una buena solución para este asunto, es decir, para disponer de un "autocompletado" en la casilla que sirve para añadir etiquetas a una determinda entrada. Además de algo sólo curioso o bonito, lo cierto es que puede resultar práctico y útil, puesto que de un vistazo permite conocer las etiquetas disponibles sobre un determinado asunto, y además, en el caso de "autocompletado" que he preparado, el número de entradas en que se usan las etiquetas.

Para implementar este asunto he utilizado el plugin Autocomplete para jQuery, que, es verdaderamente completo, todo hay que decirlo. Cuenta con las opciones suficientes y aun más (que nunca se sabe) y está probado (y comprobado) en los navegadores en que se prueba Gesbit: Firefox, Opera, Internet Explorer y Safari. El "autocomplete" se pone en marcha al escribir en la casilla para las etiquetas de una entrada. Un sólo caracter pone en marcha el mecanismos y ya nos ofrecerá posibles resultados. Es posible seguir escribiendo para ir afinando la búsqueda.

En definitiva, una nueva característica en Gesbit que creo que merece la pena. No es que sea el acabose, pero, me alegro de que ya pueda contarse con ella y quería comentarlo aquí además. ;)

Iconos de agregadores Menéame Del.icio.us Digg Technorati Blinklist
Categorías: Desarrollo
¡Orden en las clases por favor!

Vale. Lo reconozco. No se me ha ocurrido otro título más estúpido. Pero, verás que algo tiene que ver con lo que comentaré a continuación. Investigando sobre cómo implementar una determinada característica en Gesbit (básicamente, cómo pueden añadir los plugins nuevos directorios a tener en cuenta en la función "autoload" para clases en Gesbit), digo, me he encontrado con el orden en que se cargaban las clases, al menos las de una instalación "limpia" de Gesbit.

Este orden distaba ya mucho de ser aleatorio, es decir, me estoy refiriendo al orden en que se cargan las clases "principales" de Gesbit, y algunas otras auxiliares, que, puede verse en el archivo "gb-globals.php" y, como digo, sobre el que ya había dado más de una y dos vueltas. Sin embargo, hoy he querido fijarme en dicho orden de nuevo, principalmente, por la clase "GbCache", que, como sabes, también me ha preocupado y aun me preocupa. Pues bien, este era el mencionado orden:

Timer
Input
I18n
CachedFileReader
StringReader
GettextReader
GbCache

No nos fijaremos sino en las siete primeras clases (hay algunas más) para quedarnos en la clase "GbCache", precisamente. Ahora bien, lo que más me llamó la atención fue la necesidad de la clase "I18n", porque, esta a su vez requiere las tres siguientes en la lista, así que me puse a ver para qué usaba esa clase en "GbCache".

En realidad ya lo sabía: la usaba para traducir ciertas cadenas de texto que se usan en la clase "GbCache" en dos circunstancias: para mostrar una especie de mensaje "estadístico" en el pie de cada página servida desde el caché, y, para el mensaje de error que muestra Gesbit si se especifica un directorio para el caché, pero, este resulta inválido.

Ahora bien, ¿era realmente necesario traducir dichas cadenas? Según lo he visto ahora no, no lo era. El error no se mostrará "casi nunca", y, desde luego, está destinado a no mostrarse. Por otro lado, los errores "de requisitos" en Gesbit tampoco se muestran traducidos, sino en el inglés "original", y es que entonces no está siquiera disponible la clase "I18n".

Así pues, quedaba el mensaje que añade información en el pie de las páginas enviadas desde el caché. Este mensaje, hay que decirlo, es una "vacilada". Quiero decir, lo que viene a decir es, "Esta página requirió pocas consultas SQL para su creación, pero, con el caché no requirió ninguna en absoluto". Vale. Me gusta. Es verdad. Está bien. ¿Pero merece la pena traducirse?

Teniendo en cuenta que la "vacilada" significa tener que cargar cuatro clases antes que la clase "GbCache", desde luego, no parece que sea necesaria su traducción. Por lo demás, no es complicado de entender, en mi opinión. Sea como fuera, no hablamos sólo de las cuatro clases necesarias para traducir esa "vacilada", sino que hablamos de cargar el archivo de lenguaje de marras, o sea de unos 50 KB cada vez.

Visto lo visto, no me ha quedado más remedio: he decidido prescindir de la clase "I18n" en la clase "GbCache", de modo que el orden de carga se altera de este modo:

Timer
Input
GbCache

Como ves nos quedamos ahora en las primeras tres clases, puesto que con eso llegamos a la que nos interesa: "GbCache". En este punto me acordé de que la clase "Timer" realizaba una tarea "obsoleta", por decirlo así. Y claro, ya puestos, tenía que ponerme con ello. Se trata de que la clase "Timer" se usa para la vacilada comentada arriba, y en otros lugares, pero, sea como sea, para calcular el tiempo que lleva la respuesta al usario.

Para esto la clase "Timer" se instanciaba en primer lugar, precisamente, para "recoger" el tiempo de "inicio de Gesbit", de modo que después pudiera calcularse el "tiempo final", y así calcular el tiempo de la respuesta al usuario. Ahora bien, la clase "Timer" tenía sentido antes de PHP 5, puesto que, desde esta versión de PHP contamos con la variable "REQUEST_TIME" en el array super global "$_SERVER".

Dicha variable, precisamente, especifica el tiempo de inicio de la respuesta al usuario, y a partir de ella podemos después calcular cuánto tardamos en responder al usuario en total. Así que para quitar la clase "Timer" del medio ha bastado un nuevo método público en la clase "Input", "RequestTime", que proporciona la información que al cabo se perseguía con la clase "Timer".

Total, que el orden de carga de las clases en Gesbit queda tal que: "Input", "GbCache", siendo necesaria sólo una clase hasta llegar a la clase "GbCache" y que esta se ponga en marcha. Recuérdese que hablo de clases, pero, en realidad me estoy refiriendo a variables globales. En el archivo "gb-globals.php" se inicializan las principales de Gesbit, y ahora el orden queda como se ha dicho.

Input
GbCache

Luego de la clase "Input" (que realmente necesita, a no ser que le demos acaso demasiadas vueltas al asunto) la clase "GbCache" se pone en marcha, lo que quiere decir que en caso de contar con contenido en el caché, el mismo será enviado en ese punto al usuario. Algo hemos ganado, pues, con estos cambios, aunque me temo que hablemos de pocos milisegundos. Pero tal vez algos más. ¿No te parece?

Iconos de agregadores Menéame Del.icio.us Digg Technorati Blinklist
Categorías: Desarrollo
« Entradas anteriores