Tutorial: Como conectar Zend_AMF con Adobe Flex Builder 3

28 January, 2010 (14:43) | Gz.Francisco | Flex, Flex Data Services

Saludos a los flexeros del mundo, este es mi primer tutorial, como parte del Grupo de Usuarios de Adobe @RIActive.

Este tutorial está pensado para seguirse como receta de cocina y que en pocos pasos estén divirtiéndose trabajando con esta poderosa forma de conectar Flex con PHP.

Requisitos:


Contenido:

  1. Organizar es buena idea: Preparando a Zend.
  2. MiClasePHP.php: Creando una clase personalizada de PHP
  3. El marco de la puerta: Creando a Zend_AMF_Server
  4. La perilla de la puerta: Configurando Flex
  5. Con quien voy a hablar?: RemoteObject y la configuraciones.
  6. @Flex: “¿Donde estas @PHP?”. @PHP: “Aquiiiiii!!”

Introducción

Necesitas hacer llamada de una función que se encuentra en una clase PHP desde Flex y te preguntas ¿Cómo logro eso? Una de las diversas respuestas es: Zend_AMF

Zend_AMF es un paquete con el cual lograras hacer llamadas desde Flex a PHP. Zend es un framework para PHP muy potente, por lo tanto cuando el uso de los datos es extremo, esta es la mejor solución.

Preparando a Zend

Ok, ahora vamos con el primer paso operativo de esta receta.

En una carpeta del servidor http, colocaremos la carpeta llamada “Zend” la cual contendrá todo el framework que hemos bajado. Dentro del server colocaremos una carpeta que llamaremos “lib” la cual contendrá todas nuestras clases personalizadas.

Y por ultimo crearemos un archivo “zend_amf_server.php” que será el Zend_AMF_Server.

Carpetas incio

Creando una clase personalizada de PHP

Adentro de la carpeta “lib” crearemos una clase de PHP llamada “ClasePersonal” que tenga un método llamado “holaMundo” al cual se le pueda pasar un argumento de tipo string para ejecutar el ejemplo.

<?php
class ClasePersonal{
public function holaMundo($mensaje = 'Hi'){
$date = getdate();
return 'Hola desde PHP, Flex dijo: '. $mensaje .' el dia '. $date["seconds"];
}
}
?>

Como pueden observar es una clase cualquiera, no tiene alguna implementación especial o algo por el estilo.

Creando a Zend_AMF_Server

En lo personal ésta fue la parte más angustiante de todas, ya que por más que hacia copy-paste de código que obtenía en el sitio de Zend_AMF y de otros tutoriales que encontré, no salía correctamente y era porque a todos o les faltaba alguna línea u otros tenían una entrega del server distinta. La última línea de código de este PHP es la más importante de todas.

“zend_amf_server.php” será el equivalente a “gateway.php” que utiliza AMFPHP. Es la puerta de acceso al server de Zend_AMF.

Este será un pequeño archivo PHP que dará el acceso a Flex. En 6 puntos a seguir estará configurado.

Primero incluimos la librería Zend.

require_once 'Zend/Amf/Server.php';

Segundo incluimos a nuestra clase personalizada.

require_once 'lib/ClasePersonal.php';

Tercero instanciamos al Zend server.

$server = new Zend_Amf_Server();

Cuarto le enviamos a nuestro nuevo server la clase personalizada.

$server-&gt;setClass('ClasePersonal');

Quinto establecemos el método de entrega del server.

echo $server-&gt;handle();

Y como producto obtendremos un “zend_amf_server.php” con las siguientes líneas de código:

<?php
require_once 'Zend/Amf/Server.php';
require_once 'lib/ClasePersonal.php';
$server = new Zend_Amf_Server();
$server-&gt;setClass('ClasePersonal');
echo $server-&gt;handle();
?>

<mx:Nota>Sí tienen muchas clases de PHP y no tienen deseos de incluirlas al script de PHP y luego enviarlas a Zend. Pueden eliminar el segundo punto y además modifican el quinto por la siguiente línea de código antes del método de entrega del server.

$server-&gt;addDirectory('include/services/');

</mx:Nota>

Configurando a Flex

Para empezar debemos tener un proyecto de Flex abierto y crear un nuevo archivo con extensión XML adentro de la carpeta “src”.

Al siguiente archivo lo llamaremos “services-config.xml” (sin comillas) y será el encargado de decirle a Flex en donde se encuentra nuestro “zend_amf_server.php”

Este archivo es un documento en formato XML, dentro del cual colocaremos dos cosas importantes: La ruta del “zend_amf_server.php” y el nombre asignado a este canal.

En mi caso el XML contendrá lo siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="zend-service" messageTypes="flex.messaging.messages.RemotingMessage">
<destination id="zend">
<channels>
<channel ref="zend-endpoint"/>
</channels>
<properties>
<source>*</source>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="zend-endpoint">
<endpoint uri="http://localhost/zend_amf_server.php"/>
</channel-definition>
</channels>
</services-config>

Como podrán ver, el XML tiene 2 puntos críticos que son los nodos “endpoint” y “destination” dentro de los cuales se especifica la ruta del zend_amf_server y el nombre que se le asignara para identificarlo dentro de Flex.

Una vez creado y guardado el XML nos vamos a nuestro proyecto y damos clic derecho>propiedades>Flex Compiler y en donde dice “Aditional compiler arguments” (Argumentos de compilación adicionales) le agregamos el texto  -services "services-config.xml" (con los guiones y las comillas) y aceptamos los cambios con el botón Ok.

argumentos compilador

RemoteObject y las configuraciones.

Ahora sí, le daremos un nombre a cada clase que necesitemos. Claro esto también se puede hacer en AS pero aquí les va el ejemplo en MXML.

Primero crearemos la etiqueta RemoteObject.

<mx:RemoteObject id="ClasePersonal" destination="zend" source="ClasePersonal" showBusyCursor="true" fault="onConexError(event)">

Aquí una pequeña lista de los atributos que necesitan y para qué sirven:

Id: El identificador con el que llamaran a la clase.

Source: El nombre de la clase PHP que vamos a llamar.

Fault: La función que arrojara para todos los métodos de esa clase, cuando exista algún error.

ShowBusyCursor: Es para que se muestre ocupado el mouse cuando está haciendo la llamada a los servicios PHP hasta que retorne algún valor/error.

Destination: Recuerdan que en el XML llamado “services-config.xml” tenía un nodo llamado destination, pues el valor del atributo de ese nodo es el que va aquí y sirve para indicarle a este RemoteObject a donde hay que enviar todas las consultas.

Una vez que ya colocamos la instancia de RemoteObject por clase PHP, pasaremos a indicar cuáles son los métodos de la clase PHP y como los llamaremos en Flex.

<mx:method name="holaMundo" result="onResultHolaMundo(event)"/>

Atributos de la etiqueta Methods:

Id: El nombre del método de la clase PHP.

Result: la función de Flex, la cual será llamada cuando exista regreso en un método de la clase PHP

Fault: Es la función de Flex que será llamada cuando exista un error de conexión en especifico para ese método de la clase PHP. Este atributo es opcional ya que en la etiqueta RemoteObject definimos una función de error para todos los métodos de esta clase.

<mx:Nota>Estos pasos se tendrán que repetir para cada método y para cada clase de PHP.</mx:Nota>

<mx:Nota>No olviden realmente definir las funciones en AS que son los resultados de las llamadas y las que son invocadas por errores.</mx:Nota>

Llamadas a las clases y los métodos.

Bueno, con esto se ha terminado todas las configuraciones. Ahora nos enfocaremos a terminar el tutorial, con un pequeño ejemplo.

A nuestra aplicación vamos a crearle una función de nombre “init” que estará disponible para el evento creationComplete de la aplicación, está se encargara de hacer la llamada al método de la clase PHP.

private function init():void{
ClasePersonal.holaMundo("Hola PHP");
}

Como nosotros ya definimos la función de AS que será la que responda nuestra llamada al método de la clase PHP, solo haremos que en un Label nuevo, le asigne el texto que nos regreso el método de PHP y después lo instanciaremos en el escenario de Flex.

private function onResultHolaMundo(event:ResultEvent):void{
var etiqueta:Label = new Label();
etiqueta.text = event.result.toString();
this.addChild(etiqueta);
}

Con esta parte estará completo nuestro MXML. Obteniendo así el script final.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
import mx.controls.Label;
import mx.rpc.events.FaultEvent;
private function onConexError(event:FaultEvent):void{
<em>//Agregado para que arroje el error.</em>
Alert.show(event.fault.faultDetail, event.fault.faultString);
}
private function onResultHolaMundo(event:ResultEvent):void{
var etiqueta:Label = new Label();
etiqueta.text = event.result.toString();
this.addChild(etiqueta);
}
private function init():void{
ClasePersonal.holaMundo("Hola PHP");
}
]]>
</mx:Script>
<mx:RemoteObject id="ClasePersonal" destination="zend" source="ClasePersonal" showBusyCursor="true" fault="onConexError(event)">
<mx:method name="holaMundo" result="onResultHolaMundo(event)"/>
</mx:RemoteObject>
</mx:Application>

Comentarios y posibles problemas.

<mx:posibleproblema>Recuerden configurar su aplicación Flex como una aplicación de servidor PHP, ya que la seguridad de Flash Player no les permitirá acceder a un servidor http sino está corriendo bajo el mismo dominio, y si necesitan hacer llamadas entre dominios necesitaran un XML llamado “domain-config.xml” si lo requieren postéenlo y se los proporciono.</mx:posibleproblema>

<mx:comentario>Yo me he fijado que la primera vez que se hace llamada a algún método de nuestras clases, lo hace 2 veces y es porque en la primera establece la conexión y en la segunda ya hace la llamada. En la segunda llamada a algún método de la clase PHP ya no hará esto.</mx:comentario>

Asi les debe quedar la carpeta de su servidor al final. (Ahora ya tiene la version de depuracion de Flex porque lo creamos como una aplicacion de server PHP)

server final

Lo demás lo pueden colocar con todo gusto y les apoyare con mi poca pero insistente experiencia xD

Hasta pronto, nos leemos en mi siguiente post. Byte.

Gracias a @eternalmoon_ por su participación en la corrección de este tutorial.

Comentarios

Comentario de Xyrer
Fecha: January 28, 2010, 5:30 pm

Hola, que bueno que terminaste el tuto, pero tienes algunos problemitas en el html, como el del echo: echo $server->handle(); y otros por ahí, por ejemplo: private function init():void{

Me inspiraste para escribir el mio para usuarios que ya conozcan el tuyo jeje, podría incluir, endpoint dinámico, trabajo con módulos y algunos trucos que he aprendido, como los cambios que hay que hacer según la versión de php y como hacer pruebas con la clase de php antes de poner una sola linea de código en flex. Felicitaciones por el tutorial.

Comentario de Xyrer
Fecha: January 28, 2010, 5:31 pm

jaja, ya veo porque los errores, el campo de comentarios me interpretó el html, pero ya entenderás.

Comentario de yacaFx
Fecha: January 28, 2010, 5:47 pm

Muy buen tuto viejo!!!! me late los niveles de detalle y como lo explicaste =) vientos viejo!!!

Comentario de master_of_puppetz
Fecha: January 28, 2010, 6:05 pm

Yay!! excelente el tuto!! pero sabes que soy “fans” de mi super clase de NetConnection xP

Comentario de Gz.Francisco
Fecha: January 29, 2010, 12:16 am

Muchas gracias a todos ^_^

Comentario de bubu
Fecha: January 29, 2010, 5:32 pm

Excelente tuto. Muy bien explicado. Te pregunto que diferencias hay en contarte a php con Zend_amf y hacerlo directamente con amfphp…??

Comentario de Gz.Francisco
Fecha: January 29, 2010, 8:14 pm

Primero la forma de llamar a los metodos es mas directa y mas facil que con NetConection. Eso pienso yo.
La segunda es que tiene una capacidad mayor para el flujo de datos. Estamos hablando de uno de los Frameworks mas poderosos de PHP.

Creo que eso es todo. Tambien hay una aplicacion AIR que funciona como el browser de AMFPHP y es para zend, esta mas bonita ^_^

Saludos a todos.

Comentario de Rhinnno
Fecha: February 1, 2010, 4:26 pm

Vientos Paco tu aportación parecio gustar mucho, ahora cual sigue.
jeje

Comentario de juana
Fecha: February 25, 2010, 10:02 am

no entendi muy bn

Escribir comentario