Site Meter
Mar 07
Construindo aplicações Flex usando AMFPHP
 

Estou escrevendo um sistema em Flex + PHP, nesse sistema estou fazendo VO das classes PHP com as classes AS3 usando o AMFPHP para isso.

Com isso, resolvi escrever uma basicão de como fazer essa integração pois vejo muitos usuários de PHP interessados em Flex, mas sem saber por onde começar. Então vamos lá:

Primeiro postarei a estrutura de pastas que estou usando no Flex e no PHP:

FLEX:
- c:/FlexProjects/root/src
    - controllers
    - models
    - remote
    - views
    - vo


Detalhando a estrutura do Flex, eu divido meus projetos nessas quatro partes:
Controllers - Onde eu mantenho minhas classes de interação, onde manipulam alguma coisa ou faz a troca de mensagens com o PHP.

Models
- Onde eu mantenho as classes de estrutura, essas classes não fazem acesso com minhas classes remotas , elas servem como base para as classes de interação, é através dessas classes que os controllers recebem as informações para manipular os itens de tela.

Remote - No packege remote eu tenho as classes que fazem o acesso as classes do PHP. São reponsaveis pelo envio das mensagens para o PHP e fazem o Responder.

Views - Na camada view eu tenho os meus componentes Flex, seja em action script ou mxml.

VO - Onde eu tenho meus VO's, classes que espelham as classes de VO do PHP.

PHP
- c:/Apache/htdocs/root
    - controllers
    - models
    - vo


No PHP a estrutura é meio diferente, pois eu uso um Framework que eu desenvolvi para abstração de dados. Esse framework me ajudar a escrever sistemas com diferentes bases de dados sem ter que escrever mais de uma versão de sóftwares. O mesmo sistema funciona em MySQL, Oracle, MSSql e PGSql, por isso minha estrutura é meio diferente.

Controllers - Eu tenho as classes que serão acessadas pelas classes do packege remote do Flex.

Models - Na camada model eu tenho o meu framework, não mostrarei detalhes do meu framework pois não vem ao caso, nas minhas classes controllers verão que eu não uso comandos SQL's, somente chamarei métodos que já me retornarão os QueryResults.

VO - Onde eu tenho os VO's do PHP que servirão como ponte de informação com as classes VO's do PHP.

A estrutura de desenvolvimento é essa acima, agora vamos aos códigos:

Nesse exemplo eu demonstrarei como buscar os dados numa base para preencher um datagrid:
Começando pelo PHP, temos no packege VO a classe notificationVO.php

vo/notificationVO.php

<?php
    class notificationVO
    {   
        public $UserId;
        public $NotificationId;
        public $NotificationTitle;
        public $NotificationFrom;
        public $NotificationDate;
       
        public $_explicitType = "vo.notificationVO";
    }
?>


Uma coisa que deverá ser notada é que o tipo das propriedades retornadas no PHP devem ter o mesmo tipo das propriedades recebidas no PHP, nesse caso, eu retorno datas do SQL formatadas e com o tipo String para isso como não preciso filtrar nada por data, caso tenha que fazer, temos que retornar como data mesmo.

Agora faremos a classe que executará uma consulta no banco e retornará um array com os dados recuperado.

controllers/notification.php

<?php
    require_once('../fwQueryBuilder.class.php');
    require_once('Notification.class.php');
   
    /**
     * Classe de notificação de usuários
     * @name Notification
     * @todo Faz a notificação automática dos usuários
     * @version 1.0
     * @author Infinitum Technologies
     */
    class Notification
    {
        /* PRIVATES VARIABLES */
        private $Query;
        private $Notificacao;
        private $tableData;
        private $rsData;
        /* PUBLIC VARIABLES */
        public $UserId;
        public $AutenticationId;
        public $NotificationId;
        public $NotificationTitle;
        public $NotificationFrom;
        public $NotificationDate;
       
       
        public function __construct()
        {
            $this->Query = new queryBuilder();             // Notificacao acessa uma classe que faz ligação com o meu framework e efetua as consultas no banco
            // esse acesso você pode substituir por uma consulta ao banco
            $this->Notificacao = new Notificacao();
        }
       
        /**
         * Notificações de usuários
         * @name GetUserNotification
         * @access Public
         * @param Array ArrayData
         * @return Query
         */
        public function GetUserNotification($arrDados)
        {
            // instancia as propriedades de VO
            $dados = new notificationVO();
            $dados->UserId = $arrDados["UserId"];
           
            // executa o método de consulta que retorna os dados do framework
            $this->rsData = $this->Notificacao->GetNotificationUser($dados->UserId);
           
            // distruo os dados recebidos como parametro
            unset($dados);
            // crio um index e populo as propriedades com os dados retornados
            $idx = 0;
            while($dadosResult = $this->Query->Fetch($this->rsData))
            {
                $dados[$idx] = new notificationVO();
                $dados[$idx]->NotificationTitle = $dadosResult['notification_title'];
                $dados[$idx]->NotificationId = $dadosResult['notification_id'];
                $dados[$idx]->NotificationDate = $dadosResult['notification_date'];
                $dados[$idx++]->NotificationFrom = $dadosResult['notification_from'];
            }
           
            // em caso de não ter retorno do banco crio uma instancia de notificationVO para não retornar algo em branco
            if(!isset($dados))
                $dados = new notificationVO();
           
            return $dados;
        }
    }
?>


Bom o trabalho do PHP está finalizado, lembrando que estou usando AMFPHP, então no meu servidor está devidamente configurado e meu código PHP está na pasta service do amf.

Vamos agora ao Flex:

Começando pela VO do Flex que terá o mesmo nome e as mesmas propriedades do VO do PHP. A diferença é que no VO do Flex implementaremos os Getters and Setters das propriedades, vejamos:

vo/notificationVO.as

package vo{    
    [Bindable] [RemoteClass(alias="vo.notificationVO")]
    
    public class notificationVO
    {
       
        private var _UserId:int;
        private var _NotificationId:int;
        private var _NotificationTitle:String;
        private var _NotificationFrom:String;
        private var _NotificationDate:String;
       
        public function get UserId() : int
        {
            return _UserId;
        }
        public function set UserId(value : int) : void
        {
            _UserId = value;
        }
       
        public function get NotificationId() : int
        {
            return _NotificationId;
        }
        public function set NotificationId(value : int) : void
        {
            _NotificationId = value;
        }    
       
        public function get NotificationTitle() : String
        {
            return _NotificationTitle;
        }
        public function set NotificationTitle(value : String) : void
        {
            _NotificationTitle = value;
        }
       
        public function get NotificationFrom() : String
        {
            return _NotificationFrom;
        }
        public function set NotificationFrom(value : String) : void
        {
            _NotificationFrom = value;
        }
       
        public function get NotificationDate() : String
        {
            return _NotificationDate;
        }
        public function set NotificationDate(value : String) : void
        {
            _NotificationDate = value;
        }
    }
}


remote/notificationRemote.as

package remote{
    import mx.controls.Alert;
    import mx.rpc.AsyncToken;
    import mx.rpc.Responder;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.remoting.mxml.RemoteObject;
   
    import vo.notificationVO;
    
    public class NotificationRemote
    {
       
        private var notificationRO:RemoteObject;
       
        private static var instance:NotificationRemote;
        public static function getInstance():NotificationRemote
        {
            if(instance == null){
                instance = new NotificationRemote();
            }
            return instance;
        }
      
        public function GetNotificationsUser(dados:notificationVO, result:Function):void
        {
            var async:AsyncToken = notificationRO.GetUserNotification(dados);
            async.addResponder(new Responder(result, defaultFaultHandler));
        }
       
        private function defaultFaultHandler(e:FaultEvent):void{
            Alert.show(e.fault.faultDetail, e.fault.faultString);
        }
       
        public function NotificationRemote(){
            notificationRO = new RemoteObject();
            notificationRO.showBusyCursor = true;
            notificationRO.destination = 'amfphp';
            notificationRO.source = 'root._controllers.Notification';
        }

    }
}


Com a classe e o método acima acessamos a classe PHP e recebemos os dados recuperados no banco de dados. Agora mostrarei a classe e o métodos que executa o chamado ao remoteObject acima para receber os dados.

views/telaNotificacao.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="790" height="582" creationComplete="init();">
    <mx:Script>
        <![CDATA[
            import mx.containers.Grid;
            import mx.core.Application;
            import mx.events.FlexEvent;
            import mx.rpc.events.ResultEvent;
            import mx.collections.ArrayCollection;
           
            import remote.NotificationRemote;
           
            private var oRemote:NotificationRemote = NotificationRemote.getInstance();
           
            [Bindable] private var arrProvider:ArrayCollection;
            [Bindable] private var arrNotifications:Array = new Array();
           
            private function init():void
            {                 // passar o id do usuário logado como parametro
                this.GetNotification(int(1));
            }
           
            // notificação =========
            private function GetNotification(UserId:int):void
            {
                var dados:notificationVO = new notificationVO();
                dados.UserId = UserId;
                oRemote.GetNotificationsUser(dados,notificationHandler);   
            }
           
            private function notificationHandler(e:ResultEvent):void
            {
                arrNotifications = e.result as Array;
                arrProvider = new ArrayCollection(arrNotifications);
                dgNotification.dataProvider = arrProvider;
                               
                txtNumNotification.text = "("+arrNotifications.length+")";
                notificacaoRO = null;
            }
        ]]>
    </mx:Script>
   <!-- grid de notificações -->
                <mx:Canvas x="10" y="68" width="770" height="174" borderStyle="solid" borderColor="#E3E3E3">
                    <mx:DataGrid id="dgNotification" x="10" y="13" width="750" height="131" alternatingItemColors="[#F8EA50, #FCFDAB]">
                        <mx:columns>
                            <mx:DataGridColumn headerText="Id" dataField="NotificationId" width="30"/>
                            <mx:DataGridColumn headerText="Título" dataField="NotificationTitle"/>
                            <mx:DataGridColumn headerText="Rementente" dataField="NotificationFrom" width="120"/>
                            <mx:DataGridColumn headerText="Data" dataField="NotificationDate" width="80"/>
                        </mx:columns>
                    </mx:DataGrid>
                </mx:Canvas>
                <!-- barra do título -->
                <mx:ApplicationControlBar x="10" y="42" width="770" id="appbarNotifications">
                    <mx:Text id="txtNotificationtittle" text="Notificações Automáticas"/>
                    <mx:Text id="txtNumNotification" text="(0)"/>
                </mx:ApplicationControlBar>
</mx:Canvas>

Nesse caso eu não precisei usar a classe de interação e nem usar algum método do model no flex, pois fiz diretamente do componente para facilitar. Mas poderia implementar os métodos numa classe do packege model e chamá-las do componente.

Mas o post já está ficando grande de mais. E como a ideia era apenas mostrar um pouco dessa integração com o PHP fiz de um modo mais rápido.

Bom gente, não testei e não sei se está faltando alguma coisa, caso tenha algum problema favor postem um comentário ou mandem-me um e-mail que eu arrumo.

[]s.

 

 
Comentários(0) Print del.icio.us Salvar
 

Comentários (Seu comentário não aparecerá até ser aprovado.)

 
Sem comentários no momento

Autor

Paulo Teixeira

Bookmark and Share


Busca


Categorias

Adobe [25]

AIR [20]

Certificações [1]

CFUG-BR [2]

ColdFusion [14]

Consultoria [1]

Dicas [22]

Eventos [5]

Flex [23]

Flex Cookbook [1]

Geral [14]

LCDS [1]

OOP/Patterns [6]

Tutoriais [13]



Por onde ando

Adobe

AIR Feed

Ben Forta

Blog Leo Caseiro

CFGIGOLÔ

CFUG-BR Adobe Groups

CFUGBR

ColdFusion Feed

Devnet ColdFusion

Flex Feed

Got API

Lauro Santos

My Adobe Groups

My BlipFm

My Flickr

My LinkedIn

My Twitter

Pcsilva

Por que CF?

Programming Land!

Rafael Capucho

Silvio Delgado Blog

Tofinha

Why CF?


Favoritos

Você precisa ter uma conta no blog para ter favoritos


  Credenciais


  Comentários

Bom post Paulo. Realmente a evolução em relação a desempenho...

João Felipe - Jotaef

Olá, por favor, gostaria de mais informações a respeito do timesheet....

Raquel

Hi Paulo, I have just downloaded your RIABox AIR Browser to...

Theo Cosmora

Olá Paulo, Gostei da iniciativa e achei bem interessante! Parabéns! Entendo...

Fernando Arruda

Olá, Paulo. Que tal implementar nesta aplicação um módulo que gere...

Felipe Magalhães


  Parceiros


  Assine

     RSS

     LOGIN

 

  AIRRotas

  RiaBox