En pocas palabras,el generador de aplicaciones POA de zenphp es un conjunto de clases que funcionan conjuntamente para emular el paradigma de la Programación Orientada a Aspectos.
Soporta PHP 4.3.0+, la simplicidad es el objetivo del paradigma,todo es controlado por un fichero entendible a simple vista XML con definiciones de aspectos (XAD) o en español (DAX : Definiciones de Aspectos en XML).
El documento explica todos los recursos disponibles del paquete. Es una poderosa herramienta que se puede utilizar tanto como para generar aplicaciones como para utilizar scripts que se autocompilen.
Ya viene instalado, basta con estar en un directorio con permisos de escritura.
Demasiado difícil para ti? :)
En este capítulo construimos un pequeño y sencillo ejemplo para aprender los principos de la POA, suficiente para que los programadores entiendan las bases del paradigma y los mecanismos de generación sin problemas.
Primero creamos una clase sencilla que sirve de base,para adornarla con aspectos que se definen en un fichero XML. En la sección "Probando la instalación "
se explica como se comprueba si todo ha funcionado correctamente y cómo se solucionan los problemas que hayan ocurrido.
Suponemos que nuestro Diagrama de Clases en UML es tal como éste: (ver directorio tutorial)
+-------------------------------+ | Prueba | +-------------------------------+ | - mensaje: string | +-------------------------------+ | + Prueba(m: String): Prueba | | + ponerMensaje(m:string):void | | + obtenerMensaje(): string | | + mostrar(): void | +-------------------------------+
Ahora, creamos el código o si usamos aplicaciones como Andromda nos genera el código automáticamente:
/** *@example Clase Prueba de ejemplo para el generador del Paradigma de la Programación Orientada a Aspectos */ class Prueba { var $mensaje; function Prueba($m) { $this->ponerMensaje($m); } function ponerMensaje($m) { $this->mensaje = $m; } function obtenerMensaje() { return $this->mensaje; } function mostrar() { echo $this->mensaje; } }
Guardamos el fichero en el directorio de la raíz de zenphp de forma que queda así web/tutorial/clase_Prueba.php ; web/tutorial/zenphp/...
Suponemos que necesitamos llevar un control de las llamadas a los métodos, por ejemplo: añadir un sistema de Depuración, ...entonces, consideramos que queremos incluir un Aspecto de depuración.
Para insertar código en las llamadas lo que hacemos es usar el nombre de la función y con "antes" o "después" definimos dónde colocar lo <nuevo>.
La Definición XML de Aspecto te permite escribir Código PHP (o cualquier otro código) para ser mezclado, es lo que se llama una Anotación (Advice).
Lo que hacemos es escribir unos cuantos trozos de código propio (nuestro) para ser incluido en la clase Prueba, gracias a la sintaxis de XML se puede usar una jerarquía muy simple donde el elemento raíz o root es un Aspecto y soporta uno o más Puntos de Corte (Pointcuts) que es donde se "coloca" el código. Cada punto de corte contiene unos atributos que definen la localización donde aplicaremos los cambios que vienen en los nodos CDATA (el código PHP nuevo).
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE aspecto SYSTEM "../zen_esquema_poa.dtd"> <aspecto> <punto_corte auto="despues" function="ponerMensaje" clase="Prueba"> <![CDATA[ echo "Fin de la funcion " . __FUNCTION__ ."(\"" . $m . "\") .<br />"; ]]> </punto_corte> <punto_corte auto="despues" clase="Prueba" nombre_funcion="mostrar"> <![CDATA[ echo "Fin de la llamada de la funcion " . __FUNCTION__ ." .<br />"; ]]> </punto_corte> <punto_corte auto="antes" nombre_funcion="mostrar" clase="Prueba"> <![CDATA[ echo "Principio de la llamada de la funcion " . __FUNCTION__ ." .<br />"; ]]> </punto_corte> <punto_corte auto="vistazo" function="mostrar" clase="Prueba"> <![CDATA[ echo "<b>Mensaje: </b>"; procesar(); echo "<br />"; ]]> </punto_corte> </aspecto>
El primer punto_corte es un Punto de corte automático (detallado más adelante) específico para el método ponerMensaje. Su anotación imprime el nombre de la función y el contenido de la variable local $m.
El segundo punto de corte aplica la misma anotación (Advice) para todas las llamadas de la clase Prueba, al final de éstas, excepto el método "mostrar".
El tercer punto de corte es también automático y su anotación imprime un mensaje conteniendo el nombre de la función, y se aplica al principio de todos los métodos o funciones definidas del .PHP base,pero no se aplica a la función ni método llamado
"mostrar".
El último punto de corte ,otro automático, se aplica al método mostrar de la clase Prueba. Mostrará la primera línea después de los comandos del método, después mostrará la nueva línea de código HTML. Por lo tanto la función procesar(); quiere decir que es ¡el método completo!
Guarda el fichero XML como depurador.xml dentro de la carpeta donde colocaste la clase_Prueba.php ,el directorio tutorial . web/tutorial/depurador.xml
La última parte de este manual-manifiesto del generador zenphp::POA explica como aplicar el XML de aspectos a la clase original.
El motor POA de zenphp define varias funciones dependiendo de lo que necesites hacer con tu aplicación, existe una función llamada zen_crear_script que es del estilo is a require_once que compila el fichero de aspectos en una clase para cargarlas una vez hecho esto. Si el fichero compilado no existe, se compila y se intenta guardar en un fichero con un nombre único (se usa md5 para codificar el nombre). Para tareas más avanzadas se encuentra la función zen_crear_proyecto() , que ahora es utilizada por el script zenphp/generador/generar.php para crear aplicaciones de los proyectos con modelos,vistas,controladores y ayudantes.
El script que carga los ficheros es realmente nuestra aplicación xD . Con unas cuantas líneas de código se muestra como funciona la POA.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** *@desc Clase Prueba de ejemplo para el generador del Paradigma de la Programación Orientada a Aspectos */ require_once "../zenphp/generador/zen_libreria_POA.php"; // Cargar clase compilada o compilar y guardar zen_crear_proyecto("clase_Prueba.php", "depurador.xml"); // Probando $prueba = new Prueba("juaxix"); if ($prueba->obtenerMensaje() != "Autor") { $prueba->ponerMensaje("jbelon"); } $prueba->mostrar(); |
Guarda el fichero como index.php dentro de /web/tutorial/index.php
Ejecuta index.php en tu servidor y verás como se van ejecutando todas las anotaciones,justo como se han definido.
El código generador , si ha funcionado todo correctamente, debería parecerse a lo siguiente:
/** *@example Clase Prueba de ejemplo para el generador del Paradigma de la Programación Orientada a Aspectos */ class Prueba { var $mensaje; function Prueba($m) { /* zenphp::generador "antes" Codigo Auto */ echo "Principio de la llamada de la funcion " . __FUNCTION__ ." .<br />"; echo "<b>Mensaje: </b>"; |
Next section explains commom mistakes. If the compiled file exist and if its code does not match with above code, notify me via email (guilhermeblanco [at] hotmail [dot] com), messenger (same as email) or at PHP Classes.org Forums.
(Por escribir)
Visitar: http://en.wikipedia.org/wiki/Aspect-oriented_programming.
(Introducción)
La teoría que la especifica define los nombres en inglés...
Conjunto de Puntos de corte, perspectivas del sistema: depuración, muestro de datos,etc.
Una anotación o Advice es un trozo de código. Se aplica a un Punto de unión
Lugar donde se coloca ,dentro del fichero original (punto de corte) donde se puede definir dónde se va a colocar el código nuevo.
Es el conjunto de anotaciones (Advices). Código aplicado en un Punto de unión (Join Point).
Es el marco de trabajo del sistema. Más técincamente, donde el conjunto de Aspectos toman una forma concreta.
(Explicar)
(Explicar)
La idea es muy simple.
+-------------------+ | Clase_Original.php| +-------------------+ /\ || +---------------------+ ||=====================>| Clase_compilada.php | || +---------------------+ +-----------+-------------------+ | | | +-------+ +-------+ +-------+ | DAX | | DAX | . . . | DAX | +-------+ +-------+ +-------+
Con la clase original tenemos ficheros DAX (Definiciones de Aspectos en XML) que añaden y al final se guarda como la clase compilada.
Lo simple es lo que funciona
(Explicar)
(Ver fichero /zenphp/generador/zen_esquema_poa.dtd) ent.
(Explicar)
(Valores en atributos)
Es opcional, pero si no se establece, entonces el atributo "nombre" debe ser definido.
Si se incluye, entonces se ha de exponer en el Punto de Corte el códigode la anotación que se va a usar:
function obtenerLinea() { if ($this->linea < 0) { return 0; } // fin-if return $this->linea; } // fin-metodoOtro ejemplo:
<![CDATA[ try { procesar(); } catch ( Exception $e ) { die( $e->obtenerMensaje() ); } ]]>Cuando se compila,el problema se muestra:
function obtenerLinea() { /* POA "antes" Codigo Auto */ try { if ($this->line < 0) { /* POA "despues" Codigo Auto */ } catch ( Exception $e ) { die( $e->obtenerMensaje() ); } return 0; } // fin-if } catch ( Exception $e ) { die( $e->obtenerMensaje() ); } /* POA "despues" Codigo Auto */ } catch ( Exception $e ) { die( $e->obtenerMensaje() ); } return $this->linea; } // fin-metodoComo puedes ver ,la última llave está 2 niveles fuera de lo que debería estar. Se compila y se genera sin errores pero cuando,es cargado ,entonces devuelve un error fatal.
Especifica un Punto de corte propio del tipo <punto_corte nombre="MiPuntoDeUnion1, MiPuntoDeUnion2"...>...</punto_corte>
Atributo opcional para restringir el punto de corte a dicha función.
Atributo opcional para restringir el punto de corte a dicha clase.
Atributo opcional para definir qué funciones no queremos que utilicen los puntos de corte, se aplican a todas las demás.
Atributo opcional para definir qué clases no queremos que utilicen los puntos de corte, se aplican a todas las demás.
Los siguientes dos ejemplos son auto-explicativos :
<?php class Prueba2 { ... function metodo($arg1, $arg2) { // tareas aqui ... /// punto_corte: miPuntoCorte ... } ... } ?>
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE aspecto SYSTEM "zen_esquema_poa.dtd"> <aspecto> <punto_corte nombre="miPuntoCorte" clase="Prueba2"> <![CDATA[ echo "Hola mundo soy un Punto de Corte!!<br />"; ]]> </punto_corte> </aspecto>
(Introducción)
(Explicar la llamada)
(colocar aquí la función)
Valor por defecto: Directorio por defecto del directorio de las clases . Para resetar, usar zen_POA::CACHE(".");
Las clases compiladas se generarán dentro del directorio especificado.
Valor por defecto:false.
Si se cambia a "true", el código de la anotación (Advice) no será compactado, y las líneas de referencia entre la clase original y la compilada estarán formateadas de forma distinta.
Valor por defecto: false.
Para realizar construcciones "al vuelo".
Si se cambia a "true", cada vez que se ejecute el script ,se recompilará el fichero POA, incluso aunque sus ficheros (DAX
y la clase original) no hayan cambiado.