miércoles, 30 de enero de 2008

Ajax, una tarea fácil

Bueno, aunque todavía no es tan fácil como quiero que sea en un futuro, creo que es lo suficientemente fácil como para incluirlo en el framework :).

En el current del proyecto (próximamente a salir la Beta 2) ya esta andando el helper js para ajax, solo el js, pero acá un ejemplo del uso:

Esta función, expande una árbol de un menú de subcategorías:

  1. function cat_load_n_expande (cat_id) {

  2. // Parseo la variable cat_id a entero
  3. cat_id = parseInt(cat_id);

  4. // Creo el objeto ajax_helper del framework:
  5. var oajax = new ajax_helper();

  6. // Acá solo referencio a unos objetos que uso en el árbol:
  7. if (cat_id) var signito = document.getElementById("cat_" + cat_id + "_explog");
  8. if (cat_id) var linker = document.getElementById("expcmd_" + cat_id);

  9. // se le pasa la URL
  10. oajax.url = "?task=admin&acc=categorias&ajax";
  11. // le seteo un div para todos los mensajes (carga, completo, etc)
  12. oajax.set_all_divs("cat_tree_" + cat_id);
  13. // le seteo que el texto cuando se complete sea el responsetext (con true)
  14. oajax.on_complete_text = true;
  15. // El texto que va a tener el div, cuando se inicie la carga
  16. oajax.on_init_text = "Cargando arbol de subcategorias...";
  17. // Acá solo reemplazo el signo que está antes del titulo para definir que está abierto
  18. if (cat_id) signito.innerHTML = "▼";
  19. if (cat_id) linker.href = "javascript:cat_unexpande(" + cat_id + ")";

  20. // Seteo para que le mande el parametro level con el id pasado (recuerden que esto castea solo)
  21. oajax.add_param ("level",cat_id);
  22. // envio
  23. oajax.send();

  24. }//function

Bien explicada les dejo esta función, para que masomenos vena el uso del objeto.

Esta es para crear una opción en el árbol:

  1. function cat_save (sup_id) {

  2. // Creamos el objeto ajax
  3. var oajax = new ajax_helper();
  4. // Obtenemos los datos del input
  5. var cat_titulo = document.getElementById("categoria_titulo_"+sup_id).value;
  6. var cat_id = document.getElementById("categoria_id_"+sup_id).value;

  7. // Pasamos la url:
  8. oajax.url = "?task=admin&acc=save_categoria";
  9. // Le decimos que cuando termine la carga, ejecute una función
  10. oajax.on_complete_func = cat_load_n_expande;

  11. // Parámetros:
  12. oajax.add_param ("categoria_titulo",cat_titulo);
  13. oajax.add_param ("categoria_super",sup_id);
  14. oajax.add_param ("categoria_id",cat_id);
  15. // Enviamos los datos...
  16. oajax.send();
  17. cat_edited = false;
  18. }//function

No hay que preocuparse por hacerlo compatible con la mi#rd4 del IE, Firefox, opera, safari, etc. es compatible con todo (solo) y sin necesidad de hacks ni códigos extras.

Como convertir un sitio convencional a uno 100% en ajax (en 5 minutos):

Y digo 5 minutos para darles tiempo de hablar por msn nada mas. La cosa es así, si el sitio está desarrollado en el framework usa las tareas y acciones (tasks y accs), así que suponiendo por ejemplo que tenemos un sitio con 4 secciones (Portada, blog, foro, galeria) como ejemplo, las tareas serían:

www.sitioejemplo.com/?task=portada
www.sitioejemplo.com/?task=blog
www.sitioejemplo.com/?task=foro
www.sitioejemplo.com/?task=galeria

Si se usó bien la clase de templates, en los archivos de salida abría algo así:

  1. set_for_captura("CONTENIDO"); ?>

  2. Ejemplo de lo que va a salir

  3. end_captura(); ?>

La opción en el template CONTENIDO, contendría al fin y al cabo el contenido, sin menúes ni nada (si esta bien trabajado) así que si tenemos un template:

<html>
<head><!-- ##HEAD## --></head>
<body>
<div id="todo">
<div id="titulo">
<h1>Ejemplo de template</h1>
</div>

<div id="cuerpo">
<div id="menu"><!-- ##MENU## --></div>
<div id="contenido"><!-- ##CONTENIDO## --></div>
</div>

<div id="footer"><!-- ##FOOT## --></div>

</div>
</body>
</html>


Solo suponiendo xD, lo que va en el menú, el footer, la cabecera y demás se cargan otro archivo, el contenido al fin y al cabo se cargaría desde los outs de las tareas.

Supongamos que hagamos un template:

  1. <!-- ##CONTENIDO## -->

sin nada mas, el FW solo expulsará a la salida el contenido neto trabajado, entonces... se puede hacer un perfecto uso de la clase de ajax para tener un sitio en ajax, que ala vez tendría la ventaja de llegar a todo su contenido por URL (para ser indexado por buscadores por ejemplo).

En que se basaría esto:

hacemos una pequeña función en js:

  1. function go_task (task) {
  2. // definimos la ruta (? o index.php o donde se tenga el init)
  3. oajax.url = "?";
  4. // usamos el methodo GET
  5. oajax.method = "GET";

  6. // Que cargue todo en el div "contenido"
  7. oajax.set_all_divs("contenido");
  8. // Que al completar inserte lo pedido en el div definido
  9. oajax.on_complete_text = true;
  10. // Cuando inicia la carga nos pone eso
  11. oajax.on_init_text = "Cargando la pagina, espere";

  12. // La tarea
  13. oajax.add_param ("task",task);
  14. // Le avisamos al FW que será por ajax
  15. oajax.add_param ("ajax","true");

  16. // Enviamos
  17. oajax.send();
  18. }

Esa es toda la función, esto ya haría la petición y la metería en el div de contenido, ahora, fijense que le mando el parámetro ajax, esto es para identificar el pedido desde el FW, ahora, en el archivos /config/template.php, podemos poner lo siguiente:

  1. if (isset($_REQUIRE['ajax'])) {
  2. $obj_template->remove_task_cache ("forajax");
  3. } else {
  4. $obj_template->remove_task_cache ("normal");
  5. }//if

El template "forajax", seria el que solo contendría la etiqueta <!-- ##CONTENIDO## --> y se cargaría solo si se manda el parámetro "ajax", por lo que en las tareas no hay que modificar absolutamente nada, y después, esto lo tomo como idea, cargar un menú normal con las direcciones fijas, y en un js, hacer que se ejecute una funcion al principio que reemplace el contenido del menú para que las rutas sean con go_task();, así si el navegador tiene deshabilitado el JS o es un bot de un buscador, tendría los links directos sin necesidad de ajax.

Bueno cualquier cosa... está el grupo :)

martes, 15 de enero de 2008

Amtfwm; uso de packages (propuesta)

Rediseño completo del framework, basado en packages:

Este es un especie de rediseño total del framework para utilizar una forma de organización mas avanzada y robusta, y a la vez, hasta conseguir un uso mas sencillo.

Hasta ahora el framework usa un sistema de tareas, y acciones, con una salida estandart y el uso de modulos y helpers aparte de las clases del sistema, esto si bien es sencillo de utilizar, puede traer problemas a futuro en la organización del framework.

Por ejemplo, las clases sql, sql_maker, abml_base y abml_basext son del sistema de abstración de datos, pero estan al mismo nivel que otras como logs, error_man y de más.

Esto tambien proboca la carga de clases incesesarias y una depuración de estas mas compleja.


La idea con esto es dividir la aplicación en packages, donde cada “paquete” tenga sus calses y funciones independientemente del proyecto, esto en php 4 es simplemente raro, pero creo que se puede hacer una buena integración si emular muchas cosas.

Por otro lado también se erradicaria la divición “common” y “tree”, pero sin tener unido el framework con el proyecto.

Otra idea muy importanto es hacer los packetes hijos de un una aplicación web, y que la “pagina web” en cuestion sea una aplicación corriendo dentro de esta.

Hasta ahora, el archivo index.php del tree, llama al application del common, en este caso estaria el “tree” adentro del common.

Aca estaria una descripción del funcionamiento:


Uso de packages, para framework PHP

Arbol de directorios:


[root (common)]
|--- [sys]
|--- [defs]
|--- [packages]
| |--- [nombre_del_packge]
| |--- [classes]
| |--- [functions]
| |--- [tasks]
|--- [local]
|--- [data]
| |--- [cache]
| |--- [logs]
| |--- [config]
| |--- [templates]
|--- [init]
|--- [packages]
|--- [nombre_del_packge]
|--- [classes]
|--- [functions]
|--- [tasks]

Y uno de los packages (obligatorio) adentro de local, seria “main” con las tasks que tendria una estructura asi:

|--- [packages]
|--- [main]
|--- [classes]
|--- main.php
|--- [functions]
|--- config.php
|--- [tasks]
|--- [webproj]
|--- [classes]
|--- main.php
|--- ejemplo_de_tarea.php
|--- [functions]
|--- config.php
|--- [tasks]


Este paquete sería simplemente el inicial, y su función seria definir que projecto será ejecutado, este seria un packete en local.

El packete “proyecto” funcionaría con los tasks, osea, en el “index” se encargaría de llamar al packete main, este decidirá a que proyecto se invoca, que es simplemente otro package el cual tambien contendrá un main, que será el que decida en base a sus calses que tarea tratará.

Cada tarea, por ejemplo, tendra su propio main, y su “destructor” o finalizador, a la vez, cada packete.

sábado, 12 de enero de 2008

¡Amtfwm Beta 1!

Se se... me retrase mucho... encima saco una beta que rezo por falle menos de lo que me espero, jejeje, pero acá por fin.

Se pueden bajar los tar.gz de la pagina de descargas del grupo:

http://groups.google.com.pe/group/amtfwm/files

Y les paso a explicar que es cada cosa:

amtfwm-apidoc 0.3 Beta 1 (simple).tar.gz
Documentación del API generada por PHPDocumentor, en un formato simple y comodo.

amtfwm-apidoc 0.3 Beta 1.tar.gz
Documentación del API generada por PHPDocumentor, mas atractiva

amtfwm-common.0.3.Beta1.tar.gz
El framework en si

amtfwm-tree.0.3.Beta1.tar.gz
El tree, para empezar ahí los proyectos

Si no entendes como se usa el tree y el common leé la Guia de Instalación o manda un mail de ayuda al grupo.

Bueno al final así quedo:

Actualmente:

Manejo de tareas y acciones:
Mejorado del diseño original, ahora se puede llamar una accion desde otra y manejarla como un objeto.

Manejo de Logins para depuración:
Estuve comentando y agregando logins en algunas clases antes de poderlas dar de terminadas.

Manejo de templates con cache:
Funcional al 100% (igual en beta) pero no presento mas fallos.

Capa de abstracción de datos:
Como siempre... hermosa y sin errores, solo que solo esta para MySql

Capa de logica:
ABMLs y de mas... terminado, no me dio problemas, pero considerenla en Beta
Pero su uso es por decirlo.. mas que util:

$noticias = new abml_base("Noticia",$sqldb);
$rs = $noticias->data_list();

$noticias->clear();
$noticias->set("@titulo",$_POST['titulo']);
$noticias->set("@body",$_POST['contenido']);
$noticias->data_save();

Si le mando el post directamente... ¿¿lo toman inseguro?? no se imagina lo seguro que es este framework ;)

Helper para template:
Digamos que incompleto, pero lo que esta funca :)

Helper para paginación:
Util... funcionando bien

Helper para ajax:
Solo el Javascript y aclaro que no esta probado, lo incluí pero no se ilucionen

En desarrollo:

Helper de formularios
Y bueno, digamos que esta casi cocinado el helper para formularios, en la proxima versión esta seguro!
En realidad es mas lindo de lo que suena, se pueden hacer formularios de tablas con solo 2 lineas de codigo, incorpora una validación por javascript con mensajes de errores totalmente personalificables, y una forma muy facil de usar e implemetar, evitando errores comunes a la hora de hacerlos a mano xD. Tambien soporta el envio de formularios por Ajax y el armado automatico desde la tabla de la base de datos.

$form = new form_helper ("form_noticias");
$form->load_campo_from_table("Noticia",$sqlmaker->get_table_info("Noticia"));
$form->print_out();

Con eso ya se armaron un formulario que verifica los datos por tamaño, tipo, formato, por si es requerido o no por la DB con un manejo de errores hermoso, y todo esto con la posibilidad de salida en (x)html y wml, sin ningún problema

ABML_base extendida
Clase de manejo de datos de en la capa de negocios, para facilitar los abml, pero esta con internacionalización (i18n), relaciones, data extra en otras tablas y demas utilidades para no tener nada en que complicarse.

Ajax Helper
Aparte de la clase en Js, un exelente helper para manejar ajax de una forma natural y super-facil, y con utilidades muy buscadas como la subida de archivos por ajax, paginacion por ajax, y trabajando de una forma muy avanzada internamente (si estudian el js se van a dar cuenta ;-)

Y esto sigue....