feb 21

Las primeras pruebas del compactador de HTML,JavaScript y CSS integrado en zenphp ,para su uso en la clase zen_plantilla está siendo todo un éxito, aunque el algoritmo es sencillo,ya que es usado para compactar/comprimir los espacios en blanco y demás caracteres sobrantes, puede reemplazarse dicha llamada por otra función como la de la librería: minify.

Un programa de ejemplo es tan sencillo como lo siguiente:

 

<?php
require_once 'zenphp/clases/clase_zen_compactador.php';
$html = file_get_contents('http://www.elpais.es/');
$tamano_antes = mb_strlen($html, '8bit');
$compactador = new zen_compactador(array(
 'mostrar_buffer' => false
));
$html = $compactador->destructor($html);
$tamano_despues = mb_strlen($html, '8bit');
echo 'Con los espacios en blanco eliminados, el tamaño del fichero HTML se reduce de '.
    round($tamano_antes/1024, 2).
    'KB a '.
    round($tamano_despues/1024, 2).
    'KB,ahorramos '.round((1-($tamano_despues/$tamano_antes))*100, 2).
    '%<br />-----------------<br /><br />'.
    $html; 
?>

La salida obtenida es:
——————
Con los espacios en blanco eliminados, el tamaño del fichero HTML se reduce de 133.52KB a 111.55KB,ahorramos 16.46%
—————–

podeis comprobarlo :)
Si no teneis acceso afuera desde el servidor por problemas de firewall, podeis guardar la web a mano o con PERL en un fichero y luego abrirla con

$html = file_get_contents('p1.html');

No necesitamos nada más que obtener la clase desde el repositorio para hacer la prueba XD

feb 21

Con una clase RSS podemos generar contenidos en XML y en función de los parámetros hacer cosas realmente interesantes, así empezar a compartir datos como servicios,gracias a las especificaciones de RSS2.0 de fechas y actualizaciones…

Para dar un ejemplo propongo una función y después algo más complejo…

Leer el resto de la entrada »

feb 20

Decisiones importantes

20 febrero, 2008

Dicen que nuestras decisiones marcan nuestro destino, por eso debemos ser nosotros mismos quienes decidamos en nuestra vida…

Veamos, las decisiones importantes del proyecto actualmente…

  • Usar gettext para los idiomas en la parte del núcleo de zenphp y el editor Poedit para crear los ficheros de idiomas (.po). ¡Es más eficiente que el uso de cadenas y constantes!…
  • Usar PHP/GTK para el generador de aplicaciones en lugar de generar por línea de comandos (cambio de chip)
  • Basar el generador de aplicaciones en modelos XML, así se puede actualizar el generador muy fácilmente, pudiéndose construir incluso un generador de generadores.
  • Diseñar “cartuchos” de aplicaciones como “Portal.XML” que generan con las opciones pasadas una aplicación completa de un portal web

La última decisión la he tomado porque ayer encontré que existen ya mecanismos que pasan de un modelo XMI construido en un editor UML a un conjunto de ficheros de clases de PHP, por lo tanto sería absurdo volver a repetir lo que otros han construido,asi que por lo tanto ,me centro en construir una aplicación PHP/GTK que utilice mi compilador y generador de aplicaciones basado en el paradigma de la programación orientada a aspectos, que lo tengo un poco olvidado :)

Con ello se cumple el objetivo del proyecto de ser un framework de aplicaciones web y ahora estoy con la parte de generador de aplicaciones en PHP/GTK.
Ahí va una captura del editor Poedit en primer plano y Kate al fondo (gracias al uso de un manualillo) :)

Buena práctica!

feb 19

La meta del proyecto es generalizar todos los procesos de creación de una web para que sea más fácil empezar un proyecto de un sitio con todo lo que necesitemos gracias al uso de varias herramientas, la más nueva de ellas es el prototipo de generador con PHP/GTK zenphp, que se basa en la creación de proyectos como el de la Asociación Zen de Andalucía o el Proyecto Splatter. He estado realizando algunas modificaciones para tenerlo todo a punto…

Nuevos cambios:
- modelo de datos
- funciones de ficheros

Lo que podemos hacer ahora con los nuevos cambios es, un listado de imágenes como este:

 

<ul>
  <li>
      <a target="_blank" href="/media/galerias/logo2.jpg">
       <img width="23" height="23" border="0" src="/media/galerias/logo2.jpg"/>
      </a>
      <input type="checkbox" value="logo2.jpg" name="borrar_imgs[]" id="logo2.jpg"/>
  </li>
  <li>
     <a target="_blank" href="/media/galerias/logo3.jpg">
      <img width="23" height="23" border="0" src="/media/galerias/logo3.jpg"/>
     </a>
     <input type="checkbox" value="logo3.jpg" name="borrar_imgs[]" id="logo3.jpg"/>
  </li>
</ul>

asi se pueden ver/seleccionar para borrar, y ahora un mecanismo para añadirlas:

 

<div id="imagenes">
 <input name="imagenes[]" id="imagen" type="file"><br>
</div>
<a href="javascript:anadirImagen();"><img src="img/boton_anadir.gif" border="0"></a>

Se añaden dinámicamente con una función JavaScript simple como esta:

 

 

<script language="JavaScript" type="text/javascript">
var items = 1;
function anadirImagen(){
 div=document.getElementById("imagenes");
 img=document.getElementById("imagen");
 items++;
 itemnuevo="<b><label for=\"imagen"+items+"\"> Nueva Imagen " + items + "</label>: </b>";
 itemnuevo+="<input type=\"file\" id=\"imagen"+items+"\" name=\"imagenes[]";
 itemnuevo+="\"><br>";
 nodonuevo=document.createElement("span");
 nodonuevo.innerHTML=itemnuevo;
 div.insertBefore(nodonuevo,img);
}
</script>

y ahora, lo único que queda es la comunicación con PHP (todo el trabajo ha estado en diseñar el formulario y el JS :)

 

<?php
function guardar_imagenes($actual){
        $errores = "";
        zen___carga_funciones('zen_ficheros');

        if (is_array($_REQUEST['borrar_imgs']))//se marcó alguna imagen para borrar?
         $actual = array_diff($actual,$_REQUEST['borrar_imgs']);
        $array = zen_serializar(array_merge($actual,zen_guardarFicheros("imagenes",ZF_DIR_PPAL.'media/galerias/',$errores)));

        if (!empty($errores)) {
            echo $errores;
            return zen_serializar($actual); //dejar los datos como estaban
        } else {
            return $array;
        }
    }
?>

El parámetro $actual son los datos que tenia, para que no se repitan, entonces podemos obetenerlos de la siguiente forma:

 

<?php
$_REQUEST['listado'] = guardar_imagenes(
 zen_deserializar($aplicacion->bd->seleccion_unica("listado from galerias where idg=".intval($_REQUEST['idg'])))
);
?>
feb 10

En este primer tutorial se empieza buscando zenphp en google y descargando desde la consola el directorio de zenphp desde el servidor SVN de la forja, sólo el directorio trunk.
Después se muestra una aplicación super sencilla tipo “Hola mundo” y se va complicando, usando un tema por defecto, la función index() de la clase zen_html que contiene una aplicación toma la plantilla inicial de media/plantillas/es/base_web.html donde “es” es el idioma por defecto, valga la redundancia.
Si la plantilla no existe,entonces se toma del contenido de zenphp por defecto, se muestra cómo cambiar los parámetros de zen.php fácilmente.
Tiene mucho más, pero para ser el primero me ha parecido bastante.
En youtube no he podido meterlo porque no se ve apenas las letras y la Forja se queda en blanco cuando intento colgar el fichero ,creo que porque pesa 12MB…

Ahí va el enlace del vídeo en formato ogg[7MB]

Dirección de vídeos en la Forja: https://forja.rediris.es/docman/?group_id=252

Actualización: como no se puede reproducir con VLC el vídeo en (R)Windows, lo he codificado con ffmpeg2theora, ya que está grabado con recordMyDesktop y el formato por defecto es ogv, ahora es .ogg ;)

feb 8

Documentos sobre eficiencia

8 febrero, 2008

Las optimizaciones me apasionan, es por eso que he creado un nuevo documento de eficiencia con zenphp:
https://forja.rediris.es/docman/view.php/252/470/optimizacion_web.pdf
Explica las técnicas que usa el framework tanto automática como manualmente y cómo podemos mejorar la eficiencia para obtener un sobresaliente. XD

P.D.: Bueno y no se si os habréis dado cuenta que en la misma columna del blog del selector de temas he puesto un RSS de poemas zen :)

Saludos

feb 3

¿90/10?

Este post es para iniciar el estudio de comprobación de si, realmente se cumple el que una aplicación escrita en PHP siga la regla 90/10 del software, la cual nos dice que un programa pasa el 90% de su tiempo de ejecución en tan sólo un 10% de su código.

Tomando los resultados de un “profiler” PHP y analizadolos podemos ver dónde “vive” el código de nuestra aplicación y de este modo realizar las optimizaciones necesarias…Basándonos en el pasado reciente de un script, podemos predecir con una predicción razonable qué instrucciones y datos utilizará en un futuro próximo, para ello podemos usar la caché de la clase zen_cache ,el sistema de memoria de System V con las llamadas de PHP, guardar datos de consultas en una sesión, etc.

Recordemos que existen dos tipos de localidad
LOCALIDAD ESPACIAL
d(t) + k = d(t+n) con n y k pequeños
“Si se referencia un elemento, los elementos cercanos a él tenderán a ser referenciados pronto”.
Es decir, si estamos accediendo a un array, seguramente volvamos a acceder pronto a él, no tiene sentido hacer un array muy grande, deberíamos optimizar el código para no usar arrays más grandes que uno bidimensional…

“Las direcciones de memoria que se están utilizando suelen ser contiguas”.
Por eso, es mejor utilizar
JUSTIFICACIÓN: Los datos relacionados se almacenan juntos.
Las instrucciones se ejecutan secuencialmente. k = n = 1
LOCALIDAD TEMPORAL
d(t) = d(τ+n) con n pequeño
“Si se referencia un elemento, tenderá a ser referenciados pronto”.
“La información que se usará en un futuro próximo es aproximadamente la misma que se está usando actualmente”.

Para diseñar un sistema óptimo se realizan todas las posibles configuraciones en ficheros .XML que definan el comportamiento para cada parte independientemente, por ejemplo, si quiero disponer de un modelo de datos de noticias con una caché que se actualice sólo, creando un fichero .XML y a la hora de usar el zen_generador, para obtener nuestra aplicación de noticias, añadiré una propiedad para que se inserte una clase zen_cache y su configuración es:

  • que se actualice siempre que se añada/modifique/borre una noticia (o se fuerce a ello)
  • que genere los listados de noticias automáticamente y los guarde en un fichero .HTML que es mucho más rápido que generar todos los listados cada vez que se cargue el script de noticias…
  • que disponga de un administrador con soporte AJAX y un cliente básico
  • que use el tema por defecto de zenphp para mostrar la información de los modelos…

Bueno,resumidamente, es lo que estoy haciendo en estos momentos…

ene 29

Me pareció muy simple hacer sólo una clase scaffolding así que además le añadí la posibilidad de la complejidad de los modelos tipo Django, (aunque sin llaves externas, por ahora) y además le puse un tema por defecto para mostrar la información de los modelo con un presentador por defecto en HTML, y ahora un administrador con AJAX.

Las brujas :D magia AJAX? De Blogging

Para explicarlo, ¿qué mejor que una imagen?

En la imagen podemos ver un ejemplo de visualizador de contenido con soporte AJAX, la función contactar (que es llamada por el enrutador al invocar la delegación por el usuario) vincula la variable $c con el contenido de la página, que está en el padre que es la aplicación web. Dicha variable es de tipo array y se utiliza para reemplazar las #etiquetas# de la plantilla HTML usada para mostrar el contenido final, las constantes de idiomas se definen en un fichero PHP que es cargado en el constructor del visualizador donde reside esta función [en realidad donde reside es una clase heredada de esta] , que tiene una clase plantilla asociada para realizar operaciones de lectura de ficheros HTML y procesamiento de reemplazos simples y rápidos con str_replace en lugar de preg_match.
En el código se utiliza la carga de funciones, ésto quizás pueda resultar molesto pero es por temas de eficiencia el que se cargen las distintas partes de zenphp sólo cuando las necesitemos, es decir, cargaremos las funciones HTML para aplicar una validación a un formulario, además podemos insertar el código en JavaScript para añadir las validaciones que creamos oportunas.
Por último se hace una llamada a $this->mostrar_web($c); que lo que hace es tomar el array de contenido y reemplazar todas sus etiquetas para finalmente mostrar la salida por pantalla.

Las validaciones son automáticas, sólo necesitamos añadir el fichero de script y definir qué campos son los que necesitamos validar…

ene 22

Las librerías de zenphp son contenidos opcionales, no son necesarias en el núcleo,pero ayudan mucho a la hora de añadir funcionalidades a una aplicación. Primero se añadieron las librerías fundamentales como las de correo y gráficas (charts), ahora le toca el turno a las más avanzadas:

  • Librería para crear PDF’s (ezPDF)
  • Librería para crear ficheros de Excel (ExcelWriter)
  • Librería para generar descargas de ficheros (zen_descarga)
  • Librería para descargar contenido de Twitter
  • Librería para crear ficheros comprimidos (createZip )

Pongo una captura de la primera:

Captura del generador de PDF

<?php

require("zenphp/zen.php");

if (!zen___carga_clase('Cezpdf')) die("No se pudo cargar la clase PDF");

$pdf =& new Cezpdf();

$pdf->selectFont('zenphp/contenido/fuentes/Avgardm.ttf');

$x=578; $r1=25;

for ($xw=40;$xw>0;$xw-=3){

    $tono=1.0-$xw/40*0.2;

    $pdf->setLineStyle($xw);

    $pdf->setStrokeColor($tono,1,$tono);

    $pdf->ellipse(50,750,$r1);

    $r1=$r1+$xw;

}

for ($xw=40;$xw>0;$xw-=3){

    $tono=1.0-$xw/40*0.2;

    $pdf->setStrokeColor($tono,$tono,1);

    $pdf->setLineStyle($xw);

    $pdf->line($x,0,$x,842);

    $x=$x-$xw-2;

}

$pdf->ezText("Contenido PDFnn",24);

$pdf->ezImage('zenphp/contenido/img/logo.jpg',0,0,'none','center');

$pdf->ezImage('zenphp/contenido/img/img05.jpg',0,0,'none','left');

$pdf->ezText("Prueba PDF",16);

$pdf->ezStream();

?>

La única que he escrito es zen_descarga, el resto son de otros autores,pero con licencia LGPL. ;)

En un par de líneas las tenemos funcionando :)

ene 19

He dejado de estudiar Matemáticas por un día justo la semana del examen…,pero no podía dejar de pensar en que podría acabar el compilador basado en el Paradigma orientado a Aspectos antes de esta semana!…sin él, el generador no es nadie ;)

Me ha llevado mucho porque el analizador sintáctico me estaba dando problemas y no sabía por qué no me añadía los puntos de corte automáticos a la clase del fichero original ,al final ,después de mucho depurar resultó que sólo era un constructor mal declarado…¡qué típico! jaja :D

He añadido un documento explicando la idea y acabo de terminar el compilador con “pica código” incluido :D ,si,si….pica código…por tí, jejeje…, ahora los proyectos web se puede crear con un par de definiciones en XML (XAD) e incluso montar un repositorio de clases,módulos y funcionalidades con todo lo que una web necesita.

Por ejemplo si necesitáramos una cesta de la compra bastaría con descargarnos, como en CakePHP, el módulo, sin embargo aquí se añaden muchas más funcionalidades porque se permite cambiar (antes de generar) el código,todo lo que tenga nuestro proyecto de “extra”, i.e.: campos, funciones que necesitemos en cualquier lenguaje,etc…

Todo se pueden añadir en el XML como definiciones y se le pasa a zenphp para que genere las clases del proyecto, que cargará los orígenes de las definiciones y creará los ficheros.

Dejo una captura del compilador y generador funcionando.

Eso es todo por hoy, si quieres saber puedes leer más sobre Programación Orientada a Aspectos.

Close
E-mail It