Invocar funciones PHP desde Flex con AMFPHP

Adobe Flex es un framework de desarrollo que nos permite crear rápida y facilmente aplicaciones RIA (Aplicaciones de Internet Enriquecidas), basado en la plataforma Flashcombinando el lenguaje de marcas MXML ActionScript. También, gracias a su entorno de desarrollo se simplifica el desarrollo de aplicaciones AIR.


En esta oportunidad quiero explicar cómo hacer uso de Flex para invocar funciones hechas enPHP (no entraré en detalles, pues no conozco a fondo ActionScript). Una forma de hacerlo es mediante AMFPHP. Pero ¿qué es AMFPHP? Es un RPC (Llamada a Procedimientos Remotos) que nos permite comunicar datos de aplicaciones-funciones entre el cliente (JavaScript, Flash, Flex, etc) y servidor (PHP, ASP, JSP, etc). En este caso AMFPHP realiza la comunicación de procesos remotos entre Flash (y por extensión aplicaciones RIA en Flex y AIR) y PHP.


Vamos por paso para la implementación de un proyecto en Flex que llame a funciones en PHP.


1. Descargar y extrae la carpeta amfphp que contiene la siguiente estructura (y para no perderse en el tutorial, colocala en la raíz de tu sitio web de tal forma que quede así:http://localhost/amfphp)



+ ampphp
 
+services
 
+core
 
+browser
 
-gateway.php
 
-globals.php
 
-.htaccess
 
-json.php
 
-xmlrpc.php
 
-phpinfo.php

2. Verificar el funcionamiento del amfphp. Para ello abres tu navegador y escribeshttp://localhost/amfphp/browser. Aparecera una ventana de configuración donde se muestra la ubicación del archivo gateway que actuará como puerta de enlace. En esta ventana solo dale clic en Save.


Podrás apreciar un especie de explorador. En la vista árbol a tu izquierda se mostrarán todas las clases en PHP que podemos usar. Para que una clase aparezca allí debes guardarla en el directorio services.


3. Vamos crear una clase en PHP. Vamos a lista una relación de clientes de una base de datos MySQL. La estructura de la tabla es la siguiente (ingresa un par de registros luego):



CREATE TABLE IF NOT EXISTS `cliente` (
 
`id` tinyint(7) NOT NULL auto_increment,
 
`nombres` varchar(50) NOT NULL,
 
`ciudad` varchar(50) NOT NULL,
 
`sexo` char(1) NOT NULL,
 
`telefono` varchar(10) NOT NULL,
 
`fecha_nacimiento` datetime NOT NULL,
  KEY
`id` (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

En archivo PHP debe tener el mismo nombre que la clase, en este caso se llama sample.php:



<?php
class sample{
   
function getUsers () {
        $mysql
= mysql_connect(localhost, "root", "");

        mysql_select_db
( "empresa" );

                $Query
= "SELECT * from cliente";
                $Result
= mysql_query( $Query );
               
while ($row = mysql_fetch_object($Result)) {
                        $return
[] = $row;
               
}
               
return( $return );
       
}
}
?>

Volvamos a http://localhost/amfphp/browser y podemos apreciar en la lista de servicios, a la mano izquierda, nuestra clase llamada sample. Si la seleccionamos se muestran sus métodos, en este caso getUsers, y pulsamos el botón call se mostrará el resultado en la parte inferior.


amfphp browser


4. Abrimos Flex (en mi caso Flex Builder 3) y creamos un nuevo proyecto Flex de nombresample.


new project


new project


Configuramos la ruta en nuestro servidor local:


new project


new project


El archivo autogenerado sample.mxml lo dejamos allí por un momento. Ahora vamos agregar un archivo de ActionScript a nuestro proyecto, para ello le damos clic derecho en la carpeta srcy seleccionamos New ActionScript File.


new project


new project


El archivo RemotingConnection.as contiene un clase que llama a una conexión remota especificando la url de ésta.



package {
       
import flash.net.NetConnection;
       
import flash.net.ObjectEncoding;

       
public class RemotingConnection extends NetConnection
       
{
               
public function RemotingConnection( sURL:String )
               
{
                        objectEncoding
= ObjectEncoding.AMF0;
                       
if (sURL) connect( sURL );
               
}

               
public function AppendToGatewayUrl( s : String ) : void
               
{
                       
//
               
}
       
}
}

Ahora el archivo autogenerado sample.mxml, lo reemplazamos por el siguiente contenido:



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

       
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns="*" creationComplete="initApplication()">

       
<mx:DataGrid dataProvider="{dataProvider}">
               
<mx:columns>
                               
<mx:DataGridColumn headerText="ID" dataField="id"/>
                               
<mx:DataGridColumn headerText="Nombres" dataField="nombres"/>
                               
<mx:DataGridColumn headerText="Ciudad" dataField="ciudad"/>
                               
<mx:DataGridColumn headerText="Telefono" dataField="telefono"/>
                               
<mx:DataGridColumn headerText="Sexo" dataField="sexo"/>
                               
<mx:DataGridColumn headerText="Fecha Nacimiento" dataField="fecha_nacimiento"/>
                       
</mx:columns>
       
</mx:DataGrid>

       
<mx:Script>
                <![CDATA[
                        [Bindable]
                        public var dataProvider:Array;
                        public var gateway : RemotingConnection;

                        public function initApplication()
                        {
                                gateway = new RemotingConnection( "http://localhost/amfphp/gateway.php" );
                                gateway.call( "sample.getUsers", new Responder(onResult, onFault));
                        }

                        public function onResult( result : Array ) : void
                        {
                                dataProvider = result;
                        }

                        public function onFault( fault : String ) : void
                        {
                                trace( fault );
                        }
                ]]>
       
</mx:Script>

</mx:Application>

Hemos creado un DataGrid para mostrar los datos de la consulta al servidor MySQL. Dentro de las etiquetas <mx:Script/> hacemos uso de ActionScript para llamar a la claseRemotingConnection que creamos anteriormente. La función initApplication() se encarga de conectar con la puerta de enlace: gateway.php, y llama al método getUsers() de la clasesample. La respuesta la recibe la función onResult() que pasa los datos a la variabledataProvider y ésta pasa al DataGrid.


6. Ahora simplemente compilamos el proyecto (Ctrl + F11) y podemos apreciar el resultado en el navegador web.


new project


De esta forma podemos crear aplicaciones web complejas que incluyan inserción y actualización de datos. Pero eso no esto, incluso podemos crear aplicaciones de escritorio gracias a AIR con esta funcionalidad, es decir llamadas a procesos remotos. Les dejo los archivos de este tutorial para que lo prueben en su servidor local.


Lo vi en: Flex and PHP Using AMFPHP

7 comentarios:

  1. tengo Windows Server 2008 r2, pruebo el amfphp en el localhost, por medio del browser y mi servicio insertar.php, funciona, inserta en la base de datos y no arroja errores, pero cuando lo pruebo desde mi aplicacion en flash, no responde, y cuando lo hace me sale un error de "no poder insertar". Qué debo hacer?

    A mi me funciona muy bien en un servidor local apache2triad, funcionando tanto el browser del amfphp como la aplicacion flash desde la que inserto un resultado en la bd mySQL

    gracias

    ResponderEliminar
    Respuestas
    1. Lo que podrías hacer sería loggear la app, para ver que cadenas esta enviando a la bd, algún carácter que no sea escapado correctamente. Si usas SQL Server, puedes poner el profiler a capturar datos de las peticiones. Para el caso del servidor, quizá sea problema de seguridad de los dominios. Es decir que necesites modificar alguna política. O en el mejor de los casos, le des permisos a la ip x.x.x.x en el servidor y.y.y.y, Saludos.

      Eliminar
  2. yo logre mandar datos via un php en flex mobile via un php sin usar ningun rpc, quisera saber si es posible que ahora haga la invrsa es decir si los mande con un post, traerlos con un get a mi base de datos del dispositivo

    ResponderEliminar
    Respuestas
    1. Si, de hecho podrías usar una implementación parecida a la se muestra en esta entrada: http://www.switchonthecode.com/tutorials/sending-flex-data-to-php-using-xml, espero te pueda servir. Saludos!

      Eliminar
    2. mira, mi problema no es mandar los datos a web, eso ya lo hice, descarte los xml porq me permiten un numero limitado y no se pueden descargar en el dispositivo, lo que yo quiero es q si yo mando los datos de flex a web con un post ahora lo que quiero es obtenerlos con un get en flex, no se si puedas ayudarme con eso, esq es lo ultimo que me falta para terminar mi proyecto

      Eliminar
  3. Si mandas datos desde Flex-->PHP puedes recogerlos con un $_REQUEST, no sé si esto te ayude en lo que estas haciendo. Desde flex podrías invocar una url parecida a: http://miservicio/pagina.php?funcion=x&datos1=y&datos2=z&otraCosa=15, algo así.

    ResponderEliminar
  4. ok, pero podrias poner un ejemplo o pasarme la url de un sitio donde encuentre algo parecido y el request en php suena bn, pero en flex, como le haria para pedir los datos, es decir, uso un request en php para obtenerlos, pero esos datos, domo los cacho con flex para insertarlos en la bd del dispositivo

    ResponderEliminar