Comunidad de diseño web y desarrollo en internet online

Conectar Flex, PHP, MySQL y WebORB para novatos

En este tutorial aprenderás desde cero a obtener datos desde una base de datos en MySQL y a representarlos en un DataGrid de Flex. Desde la configuración de WebORB hasta el código Actionscript 3, hecho fácil.

Para lograrlo:

  1. Instalaremos WebORB, como agente de intercambio Cliente/Servidor en formato AMF3, el cual funciona con Flex perfectamente. Gracias a WebORB podremos acceder fácilmente a los Servicios PHP que desarrollaremos para nuestro ejemplo en Flex.
  2. Crearemos una base de datos en MySQL muy sencilla, a través de phpMyAdmin para el ejemplo.
  3. Escribiremos una clase/servicio en PHP y la registraremos en WebORB.
  4. Y finalmente, construiremos una pequeña aplicación en Flex Builder 2, que acceda al Servicio PHP creado, y rellene un DataGrid con los datos recibidos.

NOTA: Si desconoces alguno de los conceptos anteriores, te recomendamos leer estos tutoriales: Tutorial de Flex Builder 2, Tutorial básico de bases de datos, Crear una base de datos MySQL desde cPanel.

Todo esto lo haremos, paso a paso y explicando el porqué de cada cosa, desde los conceptos más elementales, hasta los más avanzados, para que al final del tutorial entiendas perfectamente, qué, cómo y porqué de todo lo que se está manejando.

Empecemos por el principio...

Voy a comenzar, explicando los conceptos fundamentales que rigen la filosofía de trabajo Cliente/Servidor que representa RemoteObject.

Estamos acostumbrados a usar archivos de texto, XML, SOAP, HTTPServices, etc, como servidores de datos remotos. Todos ellos se basan en un modelo de representación plano, es decir, la aplicación oyente recibe de sus orígenes un texto plano estructurado, que es parseado y tratado apropiadamente por nuestros algoritmos personales.

Adobe agregó a Actionscript 3 (Y por ende a Flex) el estándar E4X que realmente ayuda mucho en el parseo de este tipo de orígenes, pero aún así seguimos limitados a un procesamiento previo al uso efectivo de los datos, con código adicional en nuestros desarrollos. A esto se suma la perdida del tipo de datos, carencia que deberíamos resolver nuevamente a mano.

Aún con todo, para aplicaciones sencillas suele ser una muy buena opción de uso, ya que no requieren alto rendimiento ni integridad de tipos, cosa que se vuelve fundamental en una aplicación un poco más seria, como sería una Rich Internet Application.

Para salvar esta problemática apareció Flash Remoting, que aportaba un protocolo de transporte de datos en formato binario, al cual llamaron AMF0, pensado para trabajar con ColdFusion como agente de transporte. Este protocolo permitía hacer uso de objetos complejos de una manera cuasi-transparente entre nuestro Flash y los servicios AMF que se ejecutaban en el servidor a través de un agente de transporte que codificaba y descodificaba el protocolo contra las clases servicio que se les registraban, el más famoso y efectivo de la época AMF0 es sin duda AMFPHP para PHP y OpenAMF para Java. En resumen: Permitía transferir objetos y variables entre Flash y un lenguaje del servidor (PHP, Coldfusion, Java) sin que se perdiera el tipo de datos.

Para sacar partido a la ventaja que este protocolo ofrecía, crearon un tipo de objeto en Flash al cual llamaron RemoteObject, el cual permitía ejecutar RPC's (Remote Procedure Call) o sea llamadas a procedimientos remotos en un clase instanciada en el servidor, superando el problema del texto plano y la serialización de datos que hasta entonces sufríamos. Resumen: Un RemoteObject permite invocar funciones escritas en código del lado del servidor y usar su resultado en Flash.

AFM0 evolucionó hacia AMF3 con la llegada de Flex 2, corrigiendo varias carencias que tenía el protocolo original, y mejorando con mucho la velocidad, el peso, el modo en como se transmite la información, y sobre todo unificando criterios de llamada y construcción de clases, al estilo Java para todos los lenguajes que lo soporten.

Una vez sabes que demonios es RemoteObject y AMF3, vamos a ver como instalamos un agente de transporte que implementa AMF3 sobre PHP en el servidor, WebORB.

NOTA: Un agente de transporte es un bloque de código que permite conectar a Flex o Flash con PHP u otro lenguaje del lado del servidor.

WebORB, es la alternativa (gratis y libre) más lograda a la versión de Abobe del protocolo AMF3, el cual es LiveCycle Data Services. LiveCycle solo puede usarse en entornos Java, en cambio WebORB da soporte al protocolo en Java, .NET, PHP y Ruby on Rails, con un rendimiento muy alto y estable. El sistema para configurarlo es idéntico al que usa LiveCycle, con lo cual lo que aprendas ahora para WebORB te valdrá también para LiveCycle.

Esquema de conexión de WebORB

WebORB es la serie de archivos del lado del servidor (En PHP en este caso) que permiten a Flash o Flex conectarse directamente con PHP por medio de AMF3.

Antes de pasar a rellenar xml's como loco para configurarlo y que copies y pegues sin saber realmente que estas haciendo, voy a explicarte como funciona un agente de transporte, para que sepas porqué y para qué son los distintos xml's que tiene en configuración.

Entra al sitio de descarga de WebORB para PHP, descarga el .zip y descomprimelo en la raiz de tu sitio, de modo que todo el contenido del zip quede en www.tusitio.com/weborb/. Esta dirección será la raiz de weborb y a partir de esto empezará el tutorial.

WebORB tiene su carpeta de configuración alojada dentro /Weborb/WEB-INF/ (Buscala dentro de la carpeta donde descomprimiste el .zip). Dentro de ésta se encuentran las clases de PHP, configuración y librerias que requerirá el agente para poder generar el protocolo e incluir nuestras clases personales dentro de las clases usables en despliegue.

En Flex Builder has de indicar la ruta hasta la carpeta WebORB (contenedora de WEB-INF), para encontrar los xml's de configuración a la hora de compilar.

Dentro de /WEB-INF/flex/ la estructura que encontramos es esta:

  • data-management-config.xml
  • messaging-config.xml
  • proxy-config.xml
  • remoting-config.xml
  • services-config.xml

Los 3 primeros no se usan en WebORB para PHP, ya que hacen referencia a funcionalidades que no se pueden ofrecer en PHP, pero que si tienen soporte en su versión Java y en LiveCycle, el cual presenta la MISMA estructura de configuración.

Lo que realmente necesitamos

services-config.xml
En este fichero se le indica al agente, que servicios del protocolo va a ofrecer y como se llaman. No lo editaremos en nada, a excepción de un atributo id. Puedes copiar y pegar el siguiente código completo dentro del archivo .xml.

Analicemos su estructura. Lee los comentarios (En verde) para entender el XML

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
    <services>
        <service-include file-path="remoting-config.xml" />
            <!-- Aquí se declaran los ficheros de
                configuración a analizar.
                Por tanto leerá nuestro remoting-config.xml -->
    </services>
    <security>
        <!-- Aquí declaran los valores para autorizar el
            uso autentificado de nuestros servicios remotos -->
    </security>
    <channels>
    <!-- Aquí se definen qué y como se llaman los canales.
            Un canal, es realmente un proceso del agente
            que procesa una petición de servicio -->

        <!-- Analicemos como está definido el procesador de AMF3
            
            CHANNEL-DEFINITION
                id = Nombre para referirnos al él desde Flex. LO MÁS IMPORTANTE DE ESTE ARCHIVO ES ESTO                
                class = Clase que usará el agente para procesar el protocolo
        -->
        <channel-definition
            id="my-amf"
            class="mx.messaging.channels.AMFChannel"
        >
        
            <!-- 
                ENDPOINT
                uri = Url donde deberá dirigir la llamada Flex, (uri o url)
                class = Clase que estará esperando llamdas en esa url 
            -->
            <endpoint
                uri="/Weborb/index.php"
                class="flex.messaging.endpoints.AMFEndpoint"
            />
            
            <!-- Al resto del fichero no le daremos uso -->
  
            <properties>
                <polling-enabled>false</polling-enabled>
            </properties>
        </channel-definition>
    </channels>
    
</services-config>

Este fichero era el más complejo, ¿A que no era tan complicado?

remoting-config.xml
Éste es el que más tocaremos, de hecho el anterior viene preconfigurado en la distribución y difícilmente necesitaras tocarlo.
Este es remoting-config. Lee los comentarios (En verde) para entender el XML.

<?xml version="1.0" encoding="UTF-8"?>

<!-- Aquí, sólo el ID es lo que debes recordar -->
<service id="remoting-service"
    class="flex.messaging.services.RemotingService"
    messageTypes="flex.messaging.messages.RemotingMessage" >
    
    <!-- Irrelevante en nuestro caso, deja esto sin modificar -->
    <adapters>
        <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
    </adapters>
    
    <default-channels>
        <!-- Le decimos al agente que en caso de indicar
            lo contrario, usaremos el canal llamado my-amf
            que fué definido en el archivo anterior.
            (El nombre "my-amf" depende de nosotros y lo elegimos en el XML anterior) -->
        <channel ref="my-amf"/>
    </default-channels>
 
    <!-- Bloques como éste, serán los que añadirás en tus proyectos 
         Cada bloque representa una clase PHP que se conectará a Flex
         De nuevo, manten en mente el ID, que es lo más importante.
         Lo puedes cambiar por lo que quieras. -->
    <destination id="myweborb-service">
        <!-- El id lo usaremos para llamar desde Flex al PHP -->
        <properties>
            <!-- Ruta en el disco duro a nuestra clase PHP
                En el tutorial haremos esta ruta más adelante -->
            <source>flex.morphx.UsuarioService</source>
        </properties>
    </destination>
    
    <!-- Destino por defecto -->
    <destination id="GenericDestination">
        <properties>
            <source>*</source>
        </properties>
    </destination>
    
</service>
 

Y con esto ya sabes que es cada cosa en los xml que hay que tocar, y ademas de camino hemos añadido la configuración para nuestro ejemplo. Notese que la ruta de nuestra clase es relativa a la carpeta /Services/ dentro de la raiz de /weborb/. En esa carpeta /Services/ es donde guardaremos nuestros archivos .PHP de la aplicación.

Creamos la Base de Datos

phpMyAdmin: Administrador de base de datos instalado en todos los hosting y servidores con PHP y MySQL.

Entra a phpMyAdmin. Dentro encontramos el panel general, donde se nos ofrece la posibilidad de crear una nueva base de datos. Ahí le damos el nombre a nuestra DB (Base de datos), y especificamos con cuidado el cotejamiento y el charset, de modo que sea utf8_unicode_ci, dado que Flex usa esa codificación de caracteres, y ademas nos aseguramos la compatibilidad con cualquier cliente de otros paises. Ponle cualquier nombre a la DB.

Con la nueva DB creada, entramos al panel de administración de tablas. En esta pantalla creamos nuestra tabla de ejemplo, con esta sencilla especificación:

  • Nombre de la tabla: user
  • Campos: 2
    • campo: id
    • tipo: int, auto_increment, primary_key

    • campo: name
    • tipo: VARCHAR(255), charset: utf8

Con esta estructura, ya tenemos nuestra tabla lista para trabajar, no olvides llenarla de datos para tener algo que mostrar ;)

Si no quieres usar phpMyAdmin, este código en SQL genera la base de datos:

CREATE TABLE `user` (
    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `name` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
);

Construimos las clases para comunicar en PHP y Actionscript 3.

Crearemos dos clases que definirán la estructura de los datos que recibimos entre PHP y Actionscript 3. Estas clases se conoces como tipos complejos de datos. Para mantener este tipo complejo correcto tanto en nuestro Flex como en nuestro PHP, nos creamos dos clases gemelas, una en AS3 y la otra en PHP, de manera que lo que enviemos por PHP sea recibido identido en AS3. Para ello, indicamos en Actionscript 3 con el metatag [RemoteClass(alias=””)] donde está su pareja AMF3 escrita en PHP.

RECUERDA: PHP es el lenguaje del lado del servidor que se conecta a MySQL. Actionscript 3 es el lenguaje del lado del cliente que muestra los datos en Flex. AMF3 es el protocolo de comunicación entre PHP y Actionscript 3 que en AS3 ya está programado internamente y en PHP lo implementamos usando las librerías WebORB para PHP. En otras palabras, AMF3 es, para efectos practicos, WebORB

Código en Actionscript 3

Creamos un archivo llamado UsuarioVO.as, que colocaremos en la misma carpeta raiz del proyecto de Flex (Donde está el .mxml).

package

{

  [Bindable]

  [RemoteClass(alias="flex.morphx.UsuarioVO")]

  public class UsuarioVO {


    public function UsuarioVO() {

    }


    public var name:String = "";
  }
}

Este objeto tiene una propiedad "name" y nada más. name será el nombre de usuario a mostrar en el DataGrid, que es el campo de contenido de nuestra tabla. Este valor será llenado por medio de PHP.

Código en PHP

Versión de PHP
WebORB requiere obligatoriamente, PHP 5.

Crearemos nuetro fichero PHP en /Services/flex/morphx/UsuarioVO.php nota que la ruta de carpetas coincide con la ruta de la clase que indicamos en el XML, de ese modo AMF3 es capaz de encontrar nuestra clase PHP, y replicarla correctamente. De esto se deduce que las mayusculas y minusculas en los nombres de las carpetas ha de coincidir plenamente con la ruta indicada antes. En programación es muy importante mantener mayusculas y minusculas de manera exacta.

<?php
    class UsuarioVO {
        
        public $name;
        
        public function UsuarioVO() {

       }


    }
?>

Si os fijáis es un objeto que tiene exactamente la misma estructura que nuestro UsuarioVO.as, y de hecho sus propiedades han de llamarse exactamente igual, incluso manteniendo el mismo uso de mayusculas y minusculas.

ValueObject: Esta combinación de clases gemelas en PHP y Actionscript 3, cuyo objetivo es mantener un mismo tipo de datos entre lenguajes, se conoce como ValueObject.

Clase en PHP de conexión a MySQL. Servicio.

Vamos a crear ahora una clase servicio en PHP para nuestro ejemplo, ubicala en la misma carpeta que el PHP anterior.

Nota: Las carpetas de clases en programación se conoces como paquetes. La clase anterior tendría como su paquete a "flex.morphx"

La llamaremos UsuarioService.php, y será ésta la clase a la que nos conectaremos desde Flex, en la cual podremos usar sus metodos, por tanto es ésta la clase que hemos de asociar al “destination” en la configuración de WebORB, como vimos antes (El XML). Lee los comentarios del código (En verde) para entender su funcionamiento.

<?php

require_once ("UsuarioVO.php"); //Importamos nuestro objeto de transporte, nuestro ValueObject

class UsuarioService {

    public function UsuarioService() {

    }

    //Nuestro metodo a llamar
    public function getUsuario() {

        //Cabecera de conexión a la BD
        //DEBES CAMBIAR LOS VALORES de "SERVER", "USER" y "PASS" de acuerdo a tus datos 
        //de conexión a tu base de datos.
        $sqlconnect = mysql_connect("SERVER", "USER", "PASS");
        $db = "DBNAME"; //DEBES CAMBIAR "DBNAME" por el nombre de tu base de datos.


        if (!$sqlconnect)
            throw new Exception("No fue posible conectarse a MySQL");
        
        if (!mysql_select_db($db))
            throw new Exception("No se puede seleccionar la base de datos $db");
        
        //Ejecutamos la consulta SQL para obtener todos los registros de la tabla
        $rst = mysql_query("SELECT * FROM USER");
        
        if (!$rst)
            throw new Exception("Error en la consulta SQL");

        $respuesta = array ();
        //Array de datos a devolver.
        //De este modo nuestro ArrayCollection en Flex,
        //tendrá una serie de objectos con la propiedad "name"
        //para pasarle al DataGrid

        while ($row = mysql_fetch_object($rst))
        //Tomamos record a record y lo encapsulamos
        //en nuestro objeto de transporte
        {
            //Creación de los Objetos de Transporte
            $vo = new UsuarioVO();
            //Le añadimos a nuestro ValueObject el nombre obtenido de MySQL
            $vo->name = $row->name;

            //Añadimos a nuestro array el ValueObject creado
            $respuesta[] = $vo;
        }

        //Devolvemos el resultado hacia Flex
        return $respuesta;
    }
}
?>

Y finalmente construimos nuestro ejemplo Flex.

Código MXML en Flex

Ahora definimos nuestro MXML en Flex desde el que llamaremos a nuestro servicio PHP.

RemoteObject: Un RemoteObject es un tag de MXML que permite conectarse a un servicio PHP configurado con WebORB.

Aclaremos cuales son los principios de una llamada a través de un RemoteObject. Una llamada de éste tipo, es por definición “asíncrona”, es decir, tenemos que pedir al RemoteObject la ejecución del procedimiento que necesitemos y luego “esperar” a que el servicio nos conteste, y para ello es imperativo el delegar esa espera a un listener (Un manejador de evento), para avisarle al usuario que los datos están cargando y cuando están cargados. Visto lo anterior, se entiende que una llamada a un método remoto implica 3 acciones:

  • La llamada al método en sí.
  • Un evento “result” que entrega un ResultEvent, y es lanzado cuando nos llegan los datos.
  • Un evento “fault” que entrega un FaultEvent, y es lanzado en caso de obtener un error en el proceso.

Por lo tanto el tratamiento de los datos esperados tras una llamada tipo “servicio.getUsuario()” donde "srv" es el id de nuestro RemoteObject en Flex, no puede hacerse en la línea siguiente a ella, sino que se hará en una función a parte que será lanzada por el evento “result” y que nos pasará por parámetro un ResultEvent con los datos recibidos y lo salvaremos en un ArrayCollection.
ArrayCollection es un tipo de datos de Flex que nos encapsula un Array, con una serie de metodos de manejo que nos permiten un gran numero de operaciones avanzadas sobre la "colección" de datos, tales como: Filtros, Cursores, Ordenaciones, etc. Por ello recogemos los datos en un objeto de este tipo, que actuará como DataSet.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Script>
        <![CDATA[

                import mx.rpc.events.ResultEvent;
                import mx.collections.ArrayCollection;
                import UsuarioVO;



                [Bindable]
                private var usuarios : ArrayCollection;

                //Esto lo hacemos para forzar al compilador
                //a incluir la clase UsuarioVO en el swf de salida, 
                //de modo que reconozca los objetos recibidos desde WebORB.
                private var forceimport:Array = [UsuarioVO]; 

                private function onResult(event:ResultEvent):void{
                    usuarios = ArrayCollection(event.result); 
                    //Es necesario convertir el "result" a un ArrayCollection (Eso se llama hacer cast)
                    //Asignamos al ArrayCollection, 
                    //la colección de objetos de 
                    //transporte recibidos desde WebORB.
                }

        ]]>

    </mx:Script>

    <!-- Instanciamos un RemoteObject, le damos nombre ?srv?
    y le indicamos a que destination hace referencia, o sea
    que clase ha de usar WebORB cuando srv haga llamadas,
    que tal como vimos antes, era nuestra clase UsuarioService -->
    <mx:RemoteObject id="srv"
        destination="myweborb-service"
        showBusyCursor="true"
        fault="Alert.show(event.fault.faultString, 'Error')"
    >
        
        <!-- Declaramos qué metodo de la clase PHP vamos a usar
        y que función de Flex queremos que trate los resultados
        que ese metodo nos devuelva -->
        <mx:method name="getUsuario" result="onResult(event)"/>
        
    </mx:RemoteObject>
    
    <mx:Button x="192" y="302" label="Obtener" width="302" click="srv.getUsuario()"/>
    
    <mx:DataGrid x="192" y="10" height="284" dataProvider="{usuarios}"/>

</mx:Application>

Ahora tan solo nos queda dar de alta en /Weborb/WEB-INF/flex/remoting-config.xml nuestro “destination” tal y como vimos antes, para que el compilador de Flex encuentre la clase remota a llamar a la hora de generar nuestro swf, para ello incluiremos en dicho fichero el siguiente segmento de código (Si ya lo hiciste antes en la configuración, no necesitas duplicarlo):

<destination id="myweborb-service">
    <!-- Id para llamar desde Flex -->

    <properties>

       <!-- Ruta a nuestra clase servicio -->
        <source>flex.morphx.UsuarioService</source>

    </properties>
</destination>

Ya tenemos todo, ahora solo queda compilar en Flex y probarlo. No olvides enviar tus preguntas al foro de Flex y Actionscript 3 o al de WebORB.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate