Olá, desbravadores! Veremos hoje um tema bem interessante, o uso de flex com alguma tecnologia server-side. Neste exemplo usarei PHP, mas nada impede que seja usada outra tecnologia como ASP, JSP ou outra.
Para ilustrar, iremos construir uma enquete onde o usuário poderá votar e ver o resultado dos votos.
Vamos aos conceitos. Há varias maneiras de fornecer dados para que o flex possa exibir e/ou manipular essas informações para os usuários. Se você usa PHP, pode fazer isso com zendAmf ou com AmfPHP, se usa Java, pode usar o BlazeDs. Enfim, existem diversas formas e, nesse caso, iremos usar um componente do flex que nos permite enviar e receber dados de um arquivo no servidor.
O componente é o HTTPService, que permite acessar um arquivo no servidor. Poderíamos usar RemoteObject usando zendAmf ou AmfPHP, que é mais rápido. Porém, para esse caso em que trabalhamos com um número pequeno de dados vindo do servidor, usar HTTPService resolverá nosso problema facilmente, sem comprometer o desempenho.
Atente para os seguintes detalhes, que são muito importantes.
- O atributo url deste componente seta o arquivo que será acessado pelo flex;
- O atributo result define que método será chamado quando a requisição for finalizada;
- O atributo fault define que método será chamado quando a requisição falhar.
- Para executar a requisição, é preciso usar o método send().
Imaginemos o seguinte cenário:
Você tem uma aplicação feita em flex com o nome teste.mxml. Ao compilar esse arquivo, será gerado um arquivo com o nome teste.swf. Essa aplicação precisa receber um dado do arquivo teste.php, que está no mesmo diretório do teste.swf. Para que isso ocorra, colocamos o seguinte trecho de código na nossa aplicação flex (teste.mxml):
<mx:HTTPService id="dataRequest" url="teste.php" result="RequestResult (event);" fault="FaultHandler(event);" />
Trecho do código PHP:
echo "Dados enviado pelo PHP";
Veja na figura abaixo o comportamento dessa transação:

Ao clicar no botão, o resultado é um alerta com a mensagem “Dado enviado pelo PHP”.
E se for necessário enviar dados do flex para o php? Bom, nesse caso iremos implementar nosso código criando um método chamado enviaDado(). Nesse método usaremos o URLVariables, que nos permitirá passar os dados do flex para o lado php. Além disso, iremos utilizar o atributo method no HTTPService, definindo que os dados serão enviados para o PHP pelo método POST. Confira o novo comportamento abaixo:

O resultado é um alerta com a mensagem “Dado enviado pelo PHP com Dado do flex”. Repare que criei o objeto URLVariables e “criei as variáveis” que serão enviadas ao servidor utilizando o comando obj.Variavel = valor;. Se tiver que enviar mais informações, basta repetir esse código, mudando apenas o nome da variável e o valor.
Depois de toda essa teoria, vamos à prática. Nosso exemplo consiste em criar um aplicativo (uma enquete) que permita aos usuários votarem em opções que serão dadas e depois conferirem o resultado da enquete. Confira o fluxo da aplicação:
Fluxo – Enquete (Flex+PHP)
- Sistema – Buscar dados do servidor;
- Sistema – Montar a estrutura da enquete;
- Usuário – Escolher uma opção;
- Sistema – Exibir Alerta pedindo confirmação do voto;
- Usuário – Confirmar a opção escolhida;
- Sistema – Enviar dados para o servidor;
- Sistema – Confirma o voto;
- Sistema – Fechar o Panel da Enquete;
- Sistema – Abrir o Panel dos resultados;
- Sistema – Busca dados sobre os resultados da enquete;
- Sistema – Anima o gráfico;
- Usuário – Clica em votar novamente;
- Sistema – Volta ao passo 3.
Fluxo Alternativo – Enquete (Flex+PHP)
1.1 Sistema – Caso não consiga buscar os dados, exibe a falha e encerra.
5.1 Usuário – Caso não confirme a escolha, o sistema confirma que não houve escolha e volta ao passo 3.
6.1 Sistema – Caso não consiga buscar os dados, exibe a falha e encerra.
Confira o gráfico que ilustra o relacionamento dos arquivos:

Explicação de cada arquivo:
- FlexEnquete.mxml = Arquivo fonte com o código flex.
- FlexEnquete.swf = Arquivo gerado a partir do FlexEnquete.mxml – esse é o arquivo que o usuário acessa e que faz a comunicação com o php.
- cfg.php = Arquivo responsável pela conexão com banco de dados.
- enquete.php = Arquivo que gera os dados da enquete.
- resultados.php = Arquivo que gera os dados com os resultados da enquete.
- voto.php = Arquivo que computa os votos.
O código está todo comentado, mas vamos a alguns detalhes relevantes:
Primeiro, atentemos para os três componentes HTTPService: cada um aponta para um arquivo php, que são os responsáveis pelas transações com o banco de dados. Todos eles (HTTPService) apontam para o evento requestFaultHandler, caso algum problema aconteça com a requisição ao PHP.
O primeiro HTTPService a ser chamado é o dataRequest, ele é responsável por trazer os dados da enquete. Se tudo ocorrer bem na requisição, será evocado o método enqueteRequestResultHandler, que tratará os retorno e irá gerar a tela da enquete.
No caso de o usuário escolher uma opção, o HTTPService que será chamado será o votoRequest, que enviará os dados e retornará a resposta para o método votoRequestResultHandler, que, por usa vez, avisará o resultado ao usuário, limpará as informações referentes à opção escolhida, fechará a tela da enquete, abrirá a tela que mostrará os resultados e chamará o método send() do HTTPService enqueteRequest, que fará uma requisição ao arquivo resultado.php. No retorno, será chamado o método enqueteRequestResultHandler, que tratará os dos dados referente ao resultado da enquente.
Outro ponto muito importante foi não deixar a enquete engessada, ou seja, a quantidade de opções de cada enquete não irá influenciar no comportamento dela. Assim, em determinado momento, poderemos definir que a enquete tenha apenas duas opções e, em outro momento, poderá ter quatro opções, e nada mudará no código.
Como fazer isso? Simples: o arquivo enquete.php informa quantas opções existem para aquela enquete, no método enqueteRequestResultHandler fazemos um for, que verifica a quantidade de opções (dados.length) e fará as iterações inserindo um HBox um Label e um RadioButton para cada opção da enquete. Desse modo, garantimos que haverá a quantidade de opções que quisermos, deixando nossa aplicação Flex mais flex 😉
Por último, destaco também o comando rb.addEventListener(MouseEvent.CLICK,rbClick). Esse comando irá criar escutas para cada RadioButton. Assim, se algum desses RadioButton forem clicados, conseguiremos saber qual e poderemos capturar informações referentes à opção clicada. O método rbClick() será chamado e receberá um argumento do tipo MouseEvent. Usando o comando evt.target.id, poderemos saber que RadioButton foi clicado. Detalhe: cada RadioButton da enquete recebe em seu id o código da opção da enquete à qual se refere. Executando o comando evt.target.value, podemos pegar o valor do RadioButton. Nesse caso, defini que seria o titulo da opção.
Em relação aos arquivos php, não irei explicá-los, uma vez que o objetivo deste artigo é o flex, mas neles não tem nada demais, apenas que dois deles geram XML e um não. Qual será o que não gera, hein?
Confira abaixo a as telas da enquete, logo após um link para vê-la em ação, um para baixar o código fonte completo (inclusive com banco de dados) e, por último, confira o código fonte totalmente comentado.

Veja o aplicativo em ação: http://www.aprendaweb.com.br/flex/FlexEnquete/
Baixe o aplicativo completo com o código fonte+PHP+BD: http://www.easy-share.com/1910024777/FlexEnqueteAprendaWeb.rar
Confira o código todo comentado
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
creationComplete="ini();" width="500" height="400" backgroundColor="#ffffff" backgroundGradientColors="#ffffff">
<mx:Script>
<![CDATA[
//Importamos os controles que serão usados na aplicação
import mx.controls.RadioButton;
import mx.controls.CheckBox;
import mx.controls.Label;
import mx.containers.HBox;
import mx.controls.*;
//Importamos os eventos
import mx.events.CloseEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
//Tambem usaremos o ArrayCollection para gerar a enquente
import mx.collections.ArrayCollection;
//Array que guardará as opções
public var dados:ArrayCollection;
//Array que guardará os dados da enquete
public var enquete:ArrayCollection;
//Variável do tipo XMLList que será usado para gerar o gráfico de resultados
[Bindable]
public var resultados:XMLList;
//Método inicial
private function ini():void{
//inciamos a chamada para colher as informações sobre a enquete
dataRequest.send();
}
//Método que é chamado quando os dados da enquente são colhidos no PHP
public function dataRequestResultHandler(event:ResultEvent):void {
//Pegamos todos os nós 'opcao' no xml Gerado pelo PHP
dados = event.result.data.opcao;
//Pegamos todos os nós 'enquete' no xml Gerado pelo PHP
enquete = event.result.data.enquete;
//Colocamos a pergunta no Label com id pergunta
pergunta.text = enquete[0]["titulo"];
//Fazemos um for para inserir todas as opções da enquete
for(var n:int = 0; n < dados.length; n++){
//Para cada iteração do for inserimos um HBox
var h:HBox = new HBox();
//Adcionamos o HBox criado no Canvas com id 'op'
op.addChild(h);
//Para cada iteração do for inserimos um Label
var l:Label = new Label();
//Colocamos o titulo da opçãoo da enquente como texto do Label
l.text = dados[n]["titulo"];
//Definimos o tamnho do Label
l.width = 400;
//Adcionamos o Label dentro do HBox que acabamos de criar
h.addChild(l);
//Para cada iteração do for inserimos um RadioButton
var rb:RadioButton = new RadioButton();
/*
Aqui vai uma parte importante: adicionamos uma 'escuta' que vai
ficar observando se algum dos RadioButtons foi clicado, caso algum
seja clicado o método rbClick é acionado
*/
rb.addEventListener(MouseEvent.CLICK,rbClick);
/*
Definimos um valor para o RadioButton neste caso o titulo da opcao
da enquete.
*/
rb.value = dados[n]["titulo"];
//Definimos o id do RadioButton que será o mesmo id da opção da enquete
rb.id = dados[n]["id"];
//Adcionamos o RadioButton dentro do HBox Criado
h.addChild(rb);
/*
O for irá se repitir de acordo com a quantidade de opções que a enquete
oferece, garantindo que haja tantos elementos quantos nescessário. Caso
uma enquente só tenha duas opções o for irá se repitir 2 vezes
e inserir duas opções, se for quatro opções irá se repitir 4 vezes e assim
por diante, dando assim a essa enquente flex ;)
*/
}
}
//Método que é acionado quando um RadioButton é clicado
private function rbClick(evt:MouseEvent):void {
//Exibimos um alerta para o usuário confirmar seu voto.
Alert.show("Você escolheu a opção: "+ evt.target.value +"\n Deseja confirmar?","Atenção",3,this,
function(event:CloseEvent):void{
//Se o usuário escolher sim
if(event.detail == Alert.YES){
//dismarcamos o RadioButton
evt.target.selected = false;
//criamos um objeto para passar os dados para o PHP
var obj:URLVariables = new URLVariables();
//passamos o id da opção
obj.opCodigo = evt.target.id;
//passamos o valor(titulo) da opção
obj.opTitulo = evt.target.value;
//enviamos os dados para o código PHP definido no HTTPService
votoRequest.send(obj);
}else{
/*
se o usuário clicar em não na confirmação do voto, dismarcamos
a opção escolhida e exibimos uma mensagem avisando que o usuário
ainda não realizou seu voto.
*/
evt.target.selected = false;
resultVoto.text = "Atençao você ainda não votou! Escolha uma opção.";
}
});
}
//Métado que é chamdo quando qualquer erro de chamada aos arquivos PHP falham
private function requestFaultHandler(event:FaultEvent):void {
Alert.show(event.fault.message);
}
//Método que é chamado na resposta do envio do voto
private function votoRequestResultHandler(event:ResultEvent):void{
//Exibimos um Alerta com o texto que vem do PHP
Alert.show(event.result.toString(),"Atenção!",0,null,function():void{
//'Fechamos' a tela da enquete
pnlEnquete.visible = false;
//'Abrimos' a tela do resultado da enquete
pnlResultado.visible = true;
/*
Enviamos dados para realizar a consulta que irá gerar o resultado
da enquete
*/
var obj:URLVariables = new URLVariables();
obj.enqCodigo = enquete[0]["id"];
enqueteRequest.send(obj);
});
}
/*
Método que é chamdo na resposta do envio dos dados para realizar a consulta
que gera os dados para o gráfico
*/
public function enqueteRequestResultHandler(event:ResultEvent):void {
//colhemos os dados para o gráfico
resultados = event.result.opcao;
}
//Método para permitir o usuário votar novamente
private function votarDeNovo():void{
//'Abrimos' a tela da enquete
pnlEnquete.visible = true;
//'Fechamos' a tela do resultado da enquete
pnlResultado.visible = false;
}
]]>
</mx:Script>
<!--Componente para se comunicar com o arquivo enquete.php-->
<mx:HTTPService id="dataRequest" url="enquete.php"
result="dataRequestResultHandler(event);" fault="requestFaultHandler(event);" />
<!--Componente para se comunicar com o arquivo resultados.php-->
<mx:HTTPService id="enqueteRequest" url="resultados.php" method="POST"
result="enqueteRequestResultHandler(event);" fault="requestFaultHandler(event);" resultFormat="e4x"/>
<!--Componente para se comunicar com o arquivo voto.php-->
<mx:HTTPService id="votoRequest" url="voto.php"
result="votoRequestResultHandler(event)" fault="requestFaultHandler(event)" method="POST"/>
<!--Componente que gerá o efeito no gráfico dos resultados-->
<mx:SeriesSlide id="slideIn" duration="3000" direction="right" />
<!--Painel da enquete-->
<mx:Panel id="pnlEnquete" title="Enquete" paddingLeft="10" paddingTop="10" width="480" top="10" left="10">
<!--Label que irá conter a pergunta -->
<mx:Label id="pergunta" fontWeight="bold" />
<!--Tela que irá conter as opções-->
<mx:VBox id="op" />
<!--Label que exibirá mensagens-->
<mx:Label id="resultVoto" fontWeight="bold" />
</mx:Panel>
<!--Painel do gráfico com os resultados-->
<mx:Panel id="pnlResultado" title="Resultado" paddingLeft="10" paddingTop="10" width="480"
visible="false" top="10" left="10">
<!--Definimos o dataProvider com a variavel resultados que contém os dados vindos do banco-->
<mx:BarChart id="Chart" height="200" color="0x323232" showDataTips="true" dataProvider="{resultados}">
<!--Exibiremos as opções como legenda no eixo y-->
<mx:verticalAxis>
<mx:CategoryAxis categoryField="titulo"/>
</mx:verticalAxis>
<mx:series>
<!--chamaremos o efeito slideIn-->
<!--Os daos do eixo y será os titulos-->
<!--Os dados do eixo x será os votos-->
<mx:BarSeries id="bar" showDataEffect="{slideIn}" yField="titulo" xField="votos" displayName="Votos"/>
</mx:series>
</mx:BarChart>
<mx:HBox>
<mx:Legend dataProvider="{Chart}"/>
<mx:Button label="Votar novamente!" click="votarDeNovo();" />
</mx:HBox>
</mx:Panel>
</mx:Application>
Espero que tenham gostado! No próximo artigo, pretendo mostrar como formatar essa enquete para deixá-la com um layout muito legal. Até a próxima.



