sábado, 13 de junio de 2009

Conectar Flex MySql amfPHP - Connect Flex MySql amfPHP - Flex 3

OBSERVACION: amfPHP 1.9 es soportado hasta Php 5.2.xxx

Translation:
En este tutorial vamos a hacer que un datagrid se llene con información de una base de datos en MySQL y además vamos a crear un formulario donde podamos dejar nuestro nombre y un mensaje.

Esto lo vamos a lograr con amfphp conectándose a MySQL y flex mostrando toda la interfaz.



Lo primero que vamos a crear es crear la lógica de Base de dato de MySQL, esta lógica fue creada por una Compañero de trabajo llamado “Joel Moya” quien me dio los scripts para crear seleccionar e insertar en la base de dato:

CREATE TABLE ‘DataGridMessageTutorial’ (
‘id’ int(11) NOT NULL auto_increment,
‘name’ varchar(30) default NULL,
‘message’ varchar(300) default NULL,
PRIMARY KEY  (‘id’)
) AUTO_INCREMENT=1 ;
SELECT * From DataGridMessageTutorial ORDER BY id DESC;
INSERT INTO DataGridMessageTutorial (
id,
name,
message
)
VALUES (
NULL , 'VARIABLE 1', 'VARIABLE 2'
);"

Ya que tenemos la base de datos podemos crear nuestras funciones remotas una para consultar de la base de datos y otra para insertar en ella:

<?php
Header('Cache-Control: no-cache');
Header('Pragma: no-cache');
class DataGridService
{
var $link;
function DataGridService(){ 
$this->link = mysql_connect("localhost", "verlasco_dydUser", "mypassword") or die ("No conecta con SQLSERVER");
mysql_select_db("verlasco_dyd", $this->link);
}
function getAllMessages(){
include_once("vo/com/dyd/tutorial/vo/MessageVO.php");
$Result = mysql_query("SELECT * From DataGridMessageTutorial ORDER BY id DESC;", $this->link );
while ($row = mysql_fetch_array($Result, MYSQL_ASSOC))
{
$my_user = new MessageVO();
$my_user->id = $row['id'];
$my_user->name = $row['name'];
$my_user->message = $row['message'];

$list_of_users[] = $my_user;
}
return $list_of_users;
}
function saveMessage($obj){
$sql = "INSERT INTO DataGridMessageTutorial (
id,
name,
message
)
VALUES (
NULL , '$obj->name', '$obj->message'
);";
return mysql_query(sprintf($sql));
}
}
?>

Notemos que en la línea 16 hay un new MessageVO() y en la línea 32 se accede a 2 atributos dentro de un objeto, esto es debido a un VO o Value Object esto nos permite enviar y recibir objetos entre el cliente y el servidor, del lado del servidor se construye así:

<?php
class MessageVO {
var $_explicitType = "com.dyd.tutorial.vo.MessageVO";
var $id;
var $name;
var $message;
}
?>

Ahora que tenemos el lado del servidor listo podemos empezar a crear el lado del cliente.

Entonces creemos un Datagrid y un pequeño formulario que contenga nombre y un mensaje:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
width="600" height="630" backgroundColor="0xFFFFFF" borderStyle="solid"
borderThickness="2" borderColor="0x000000" cornerRadius="8" right="2"
left="2" top="2" bottom="2"
creationComplete="creationCompleteHandler(event)"
preloader="com.dyd.tutorial.utils.PathfinderCustomPreloader">
<mx:Script>
<![CDATA[
import com.dyd.tutorial.vo.MessageVO;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*---------------------------- START VARIABLES -------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/

[Bindable]private var myArray:Array = []

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------- END VARIABLES --------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/


/******************************************************************************/


/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*-------------------------- START INIT FUNCTIONS ----------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/

private function creationCompleteHandler(event:FlexEvent):void{
amf.getAllMessages.send();
}

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*--------------------------- END INIT FUNCTIONS -----------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/


/******************************************************************************/


/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*------------------------- START EVENT FUNCTIONS ----------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/

/*-- START EVENT CAIRNGORM --*/



/*--- END EVENT CAIRNGORM ---*/

/***************************/

/*---- START EVENT FLEX -----*/

private function acceptHandler(event:MouseEvent):void{
if( myNameTextInput.text  && myNameTextInput.text.length>0 &&
myMessageTextArea.text  &&  myMessageTextArea.text.length>0){
var messageVO:MessageVO = new MessageVO;
messageVO.name = myNameTextInput.text.toString();
messageVO.message = myMessageTextArea.text.toString();
amf.saveMessage.send( messageVO );

}else{
Alert.show("Name or Messege is Empty","Message");
}
}
private function cancelHandler(event:MouseEvent):void{
myNameTextInput.text  = "";
myMessageTextArea.text = "";
} 
private function getAllMessageResultHandler(event:ResultEvent):void{
myArray = event.result as Array;
}
private function getAllMessageFaultHandler(event:FaultEvent):void{
Alert.show("Data Base Off Line - Refresh The Application", "Message");
}
private function seveMessageResultHandler(event:ResultEvent):void{
if(event.result == true){
myNameTextInput.text  = "";
myMessageTextArea.text = "";
amf.getAllMessages.send();
}else{
Alert.show("Data Base Can't Insert - Please Try Again", "Message");
}
}
private function seveMessageFaultHandler(event:FaultEvent):void{
Alert.show("Data Base Off Line - Refresh The Application", "Message");
}

/*----- END EVENT FLEX ------*/

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*------------------------- END EVENT FUNCTIONS ------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
]]>
</mx:Script>
<mx:RemoteObject id="amf" source="DataGridService" destination="amfphp">
<mx:method  name="getAllMessages"
result="getAllMessageResultHandler(event);"
fault="getAllMessageFaultHandler(event);"/>
<mx:method  name="saveMessage"
result="seveMessageResultHandler(event);"
fault="seveMessageFaultHandler(event);"/>
</mx:RemoteObject>
<mx:DataGrid  id="myDataGrid" width="100%" height="360"
dataProvider="{myArray}" rowHeight="65">
<mx:columns>
<mx:DataGridColumn  dataField="name" headerText="Name"
width="150" wordWrap="true"/>
<mx:DataGridColumn dataField="message" headerText="Message"
wordWrap="true"/>
</mx:columns>
</mx:DataGrid>
<mx:Form width="100%" height="183">
<mx:FormItem label="Name:" >
<mx:TextInput  id="myNameTextInput" width="330" restrict="a-z A-Z"
maxChars="30" />
<mx:Label text="Restrict: a-Z.    Max Chars: 30" color="red" />
</mx:FormItem>
<mx:FormItem label="Message:" >
<mx:TextArea  id="myMessageTextArea" width="330" height="75"
maxChars="200" />
<mx:Label text="Max Chars: 300" color="red" />
</mx:FormItem>
</mx:Form>
<mx:HBox width="300" horizontalAlign="right" >
<mx:Button label="Accept" click="acceptHandler(event);" />
<mx:Button label="Cancel" click="cancelHandler(event);" />
</mx:HBox>
</mx:Application>

Creamos el VO del Lado del Cliente también para poder recibir y enviar los mismos datos:

package com.dyd.tutorial.vo
{
[Bindable]
[RemoteClass(alias="com.dyd.tutorial.vo.MessageVO")]
public class MessageVO
{
public var id:String;
public var name:String;
public var message:String;
}
}

Y el XML que se encarga de llamar al servicio:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="amfphp-flashremoting-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">

<destination id="amfphp">
<channels>
<channel ref="my-amfphp"/>
</channels>
<properties>
<source>*</source>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="my-amfphp" class="mx.messaging.channels.AMFChannel">
<endpoint uri="/amfphp/gateway.php" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>
</services-config>

Y aquí les dejo dos imágenes en las cuales vemos como son las rutas de los archivos tanto del lado del cliente como del lado del Servidor:


Ejemplo:

In this Example we want a data grid that fills from a MySQL Database and also we want to save all the messages and name from a form so anybody can leave a message.

So for this we are going to use amfphp to connect to MySQL and flex to display everything.

The first thing we have to do is Database Logic for MySQL and a co worker and also a good friend “Joel Moya” gave me the script to create select and insert in the Database:

CREATE TABLE ‘DataGridMessageTutorial’ (
‘id’ int(11) NOT NULL auto_increment,
‘name’ varchar(30) default NULL,
‘message’ varchar(300) default NULL,
PRIMARY KEY  (‘id’)
) AUTO_INCREMENT=1 ;
SELECT * From DataGridMessageTutorial ORDER BY id DESC;
INSERT INTO DataGridMessageTutorial (
id,
name,
message
)
VALUES (
NULL , 'VARIABLE 1', 'VARIABLE 2'
);"

Know with the database ready we can create the remote function in php, we are going to create 2 function one to consult and one to Insert in the database:

<?php
Header('Cache-Control: no-cache');
Header('Pragma: no-cache');
class DataGridService
{
var $link;
function DataGridService(){ 
$this->link = mysql_connect("localhost", "verlasco_dydUser", "mypassword") or die ("No conecta con SQLSERVER");
mysql_select_db("verlasco_dyd", $this->link);
}
function getAllMessages(){
include_once("vo/com/dyd/tutorial/vo/MessageVO.php");
$Result = mysql_query("SELECT * From DataGridMessageTutorial ORDER BY id DESC;", $this->link );
while ($row = mysql_fetch_array($Result, MYSQL_ASSOC))
{
$my_user = new MessageVO();
$my_user->id = $row['id'];
$my_user->name = $row['name'];
$my_user->message = $row['message'];

$list_of_users[] = $my_user;
}
return $list_of_users;
}
function saveMessage($obj){
$sql = "INSERT INTO DataGridMessageTutorial (
id,
name,
message
)
VALUES (
NULL , '$obj->name', '$obj->message'
);";
return mysql_query(sprintf($sql));
}
}
?>

Notice that in the line 16 the is an new MessageVO() and in the line 32 I can access to properties from a object, that is because we made an VO or Value Object this value Object lets us pass Object in the functions and send it back to the client:

<?php
class MessageVO {
var $_explicitType = "com.dyd.tutorial.vo.MessageVO";
var $id;
var $name;
var $message;
}
?>

Know we have the remote side complete we need the client side.

So we are going to paint a Datagrid and a little form that contains a name and a message:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
width="600" height="630" backgroundColor="0xFFFFFF" borderStyle="solid"
borderThickness="2" borderColor="0x000000" cornerRadius="8" right="2"
left="2" top="2" bottom="2"
creationComplete="creationCompleteHandler(event)"
preloader="com.dyd.tutorial.utils.PathfinderCustomPreloader">
<mx:Script>
<![CDATA[
import com.dyd.tutorial.vo.MessageVO;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*---------------------------- START VARIABLES -------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/

[Bindable]private var myArray:Array = []

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------- END VARIABLES --------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/


/******************************************************************************/


/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*-------------------------- START INIT FUNCTIONS ----------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/

private function creationCompleteHandler(event:FlexEvent):void{
amf.getAllMessages.send();
}

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*--------------------------- END INIT FUNCTIONS -----------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/


/******************************************************************************/


/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*------------------------- START EVENT FUNCTIONS ----------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/

/*-- START EVENT CAIRNGORM --*/



/*--- END EVENT CAIRNGORM ---*/

/***************************/

/*---- START EVENT FLEX -----*/

private function acceptHandler(event:MouseEvent):void{
if( myNameTextInput.text  && myNameTextInput.text.length>0 &&
myMessageTextArea.text  &&  myMessageTextArea.text.length>0){
var messageVO:MessageVO = new MessageVO;
messageVO.name = myNameTextInput.text.toString();
messageVO.message = myMessageTextArea.text.toString();
amf.saveMessage.send( messageVO );

}else{
Alert.show("Name or Messege is Empty","Message");
}
}
private function cancelHandler(event:MouseEvent):void{
myNameTextInput.text  = "";
myMessageTextArea.text = "";
} 
private function getAllMessageResultHandler(event:ResultEvent):void{
myArray = event.result as Array;
}
private function getAllMessageFaultHandler(event:FaultEvent):void{
Alert.show("Data Base Off Line - Refresh The Application", "Message");
}
private function seveMessageResultHandler(event:ResultEvent):void{
if(event.result == true){
myNameTextInput.text  = "";
myMessageTextArea.text = "";
amf.getAllMessages.send();
}else{
Alert.show("Data Base Can't Insert - Please Try Again", "Message");
}
}
private function seveMessageFaultHandler(event:FaultEvent):void{
Alert.show("Data Base Off Line - Refresh The Application", "Message");
}

/*----- END EVENT FLEX ------*/

/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*------------------------- END EVENT FUNCTIONS ------------------------------*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
]]>
</mx:Script>
<mx:RemoteObject id="amf" source="DataGridService" destination="amfphp">
<mx:method  name="getAllMessages"
result="getAllMessageResultHandler(event);"
fault="getAllMessageFaultHandler(event);"/>
<mx:method  name="saveMessage"
result="seveMessageResultHandler(event);"
fault="seveMessageFaultHandler(event);"/>
</mx:RemoteObject>
<mx:DataGrid  id="myDataGrid" width="100%" height="360"
dataProvider="{myArray}" rowHeight="65">
<mx:columns>
<mx:DataGridColumn  dataField="name" headerText="Name"
width="150" wordWrap="true"/>
<mx:DataGridColumn dataField="message" headerText="Message"
wordWrap="true"/>
</mx:columns>
</mx:DataGrid>
<mx:Form width="100%" height="183">
<mx:FormItem label="Name:" >
<mx:TextInput  id="myNameTextInput" width="330" restrict="a-z A-Z"
maxChars="30" />
<mx:Label text="Restrict: a-Z.    Max Chars: 30" color="red" />
</mx:FormItem>
<mx:FormItem label="Message:" >
<mx:TextArea  id="myMessageTextArea" width="330" height="75"
maxChars="200" />
<mx:Label text="Max Chars: 300" color="red" />
</mx:FormItem>
</mx:Form>
<mx:HBox width="300" horizontalAlign="right" >
<mx:Button label="Accept" click="acceptHandler(event);" />
<mx:Button label="Cancel" click="cancelHandler(event);" />
</mx:HBox>
</mx:Application>

The VO we are sending we have to have it to in the client side so let’s made it:

package com.dyd.tutorial.vo
{
[Bindable]
[RemoteClass(alias="com.dyd.tutorial.vo.MessageVO")]
public class MessageVO
{
public var id:String;
public var name:String;
public var message:String;
}
}

And the XML that refers to the service:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="amfphp-flashremoting-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">

<destination id="amfphp">
<channels>
<channel ref="my-amfphp"/>
</channels>
<properties>
<source>*</source>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="my-amfphp" class="mx.messaging.channels.AMFChannel">
<endpoint uri="/amfphp/gateway.php" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>
</services-config>

Here are two image of the directory of the file from the server side and the client side:


Example:




Descargar Archivo y Ver Codigo Fuente:


Download File's and Source:

2 comentarios :

  1. hola buen aporte !!! =D
    lo unico que me queda duda es de donde sale el preloader

    -preloader="com.dyd.tutorial.utils.PathfinderCustomPreloader">-

    solamente eso =S
    gracias de ante mano

    ResponderBorrar
  2. Estimado Davizero

    Puedes borrar esa clase ya que solo sirve para el loader con nuesto logo de todos los archivos SWF, puedes borrar esa linea con confianza y se regresara al loader por defecto.

    Saludos.

    ResponderBorrar