Proposta de Arquitetura com Adobe Flex e PHP usando Zend Framework

Olá Pessoal,

Um item básico quando se trata de sites, é um local onde o visitante pode de alguma forma entrar em contato com a empresa do site, hoje existem algumas boas soluções para isso, como por exemplo um client msn que pode ser colocado no site e se o visitante quiser, pode entrar em contato com o msn da empresa.

Mas hoje vou mostrar a vocês uma forma simples e funcional, que consiste em um formulário onde o visitante preenche os dados, e gera um e-mail para o destinatário.

Mostrarei isso usando PHP/ZEND/AMFPHP/FLEX, poderia fazer isso somente com HTTPService? concerteza, ficaria menos código e até mais simples, porém concordamos que ninguém iria fazer uma aplicação só com essa funcionalidade, pois o Formulário de Contato seria apenas um módulo do sistema.

Então vou lhes mostrar também uma proposta de como você pode trabalhar arquiteturalmente com Flex e PHP, trocando apenas VO/TO/DTO entre as camadas, lembrando que isso é uma boa prática, vejo muitos porae trocando array’s com Flex e PHP, isso é totalmente desnecessário.

Detalhes da Arquitetura

ZEND Framework;

AMFPHP;

Adobe Flex;

A arquitetura usa o ZEND para abstração do banco de dados usando a Classe Zend_Db_Table, e outros recursos como o Zend_Loader e Zend_Registry.

AMFPHP para a comunicação entre o AdobeFlex e o PHP, esta comunicação rodando em cima do protocolo AMF3, que provém comunicação binária não mais String como no HTTP puro, e também compactação.

Estruturando a aplicação

Estrutura de Pastas  
Listagem 1

Crie uma estrutura de pastas como mostrado na Listagem 1

O package entitybean contém classes que segue os conceitos de um EntityBean como nas especificações J2EE/JEE, só que claro BMP através do Zend_Db_Table, e uma outra classe que eu fiz chamada EntityBeanImpl, que abstrai ainda mais os métodos CRUD de um caso de uso, como por Exemplo eliminei os métodos Inserir e Atualizar, e criei um Salvar, que insere ou atualiza baseado na Primary-Key. Em poucas palavras, um EntityBean, é reponsável pela abstração de um Banco de Dados Relacional, as camadas acima de entityBean apenas conhecem o entitybean, não tem acesso ao Banco de dados.

Para Garantir transação e concorrência, criei uma classe chamada DB que cotém um singleton me garantindo apenas uma instância da mesma em uma transação,  ela é reponsavel por iniciar uma transação através do método beginTransaction() realizar o commit se toda a operação ocorrer com sucesso atraveés do método commit()  e realizar o roolback no banco de dados através do método rollback().

O package sessionbean contém classes que segue os conceitos de um SessionBean também como nas especificações J2EE/JEE só que apenas sendo Stateless. Em poucas palavras um SessionBean tem a responsábilidade de implementar a regra de negócio do caso de uso, como por exemplo validações, calculos e etc.

O package facade contém classes que implementam o Pattern Facade em outras palavras é a fachada do sistema, neta arquitetura ela é responsável por garantir a transação usando a classe DB, também é reponsável pelo tratamento de exceções (Erros).

O package vo contém simples classes que implementam os Patterns VO/TO/DTO, são os vo’s encarregados de transportar entre as camadas as informações de cada caso de uso. Lembrando que o mesmo VO no PHP, será automaticamente serializado pelo AMFPHP para um VO no Flex para isso os VO devem ficar assim:

No PHP:
*Coloque a tag do php no inicio e no fim.
[php]

class ContatoVO
{
    var $idContato;
    var $dsNome;
    var $dsEmail;
    var $nuTelefone;
    var $dsCidade;
    var $dsEstado;
    var $dsMensagem;

//NOME DO VO NO FLEX
    var $_explicitType = “ContatoVO”;
}

[/php]

No Flex/AS3
[as]

package com.digows.Artigos.FlexPHP.vo
{
    //NOME DO VO NO PHP
     [RemoteClass(alias=”ContatoVO”)]
    [Bindable]
    public class ContatoVO
    {
        public var idContato:int;
        public var dsNome:String;
        public var dsEmail:String;
        public var nuTelefone:String;
        public var dsCidade:String;
        public var dsEstado:String;
        public var dsMensagem:String;
    }
}

[/as]

O package services contem as classes de serviços de toda aplicação, estes serviços podem ser disponibilizados para o AMFPHP como veremos a seguir, ou também se você conhece bem o Zend Framework, pode gerar serviços através de WebServices ou até mesmo serviços para o Controller do Zend Framework, neste caso usando HTML na View.

O package config apenas contém arquivos de configuração, como por exemplo path do servidor, dados do banco de dados e etc.

E finalmente o package libs que contém as bibliotecas utilizadas na aplicação, no caso o AMFPHP e Zend Framework.

Configurando a aplicação

Nós precisamos fazer uma integração com o Zend Framework, e o AMFPHP, então primeiramente vamos gerar o application-config.php do Zend.

Dentro do package config, crie um arquivo chamado application-config.php  com este conteúdo:

*Coloque a tag do php no inicio e no fim.
[php]

set_include_path(‘.’.PATH_SEPARATOR.’../../libs’.PATH_SEPARATOR.get_include_path());
    require_once (‘Zend/Loader.php’);
    /**
    * Loaders
    */
    //Registrador de Variaveis
    Zend_Loader::loadClass(‘Zend_Registry’);
    //Carregador de configuracoes de um .ini
    Zend_Loader::loadClass(‘Zend_Config_Ini’);
      //Classe que encapsula o Banco
    Zend_Loader::loadClass(‘Zend_Db’);
    //Classe para usar as tabelas como objetos.
    Zend_Loader::loadClass(‘Zend_Db_Table’);
    //Usada para fazer o parser dos xml
    Zend_Loader::loadClass(‘Zend_Config_Xml’);

/**
    * Configuracoes da Persistencia.
    */
    //Carrega o arquivo de configuracoes.
    $configDB = new Zend_Config_Ini(dirname(__FILE__).’/config.ini’, ‘database’);
    Zend_Registry::set(‘configDB’, $configDB);
    $configPaths = new Zend_Config_Ini(dirname(__FILE__).’/config.ini’, ‘paths’);
    Zend_Registry::set(‘configPaths’, $configPaths);
    /**
     * Configuracoees variadas…
     */
       //Configura o formato para moeda
      setlocale(LC_MONETARY, ‘ptb’);
    //Configura as mensagens de erro que devem ser apresentadas.   
    error_reporting(E_ALL | E_STRICT);

[/php]

Perceba que a configuração usa um arquivo chamado config.ini este contém as configurações do Banco de Dados e paths:


[database]
db.adapter=PDO_MYSQL
db.config.host=localhost
db.config.username=root
db.config.password=
db.config.dbname=flexphp
[paths]
path.dirImg=C:/resources/img

No package libs você coloca os arquivos do ZEND e do AMFPHP ficando assim:

Libs
Listagem 2

A única coisa que precisa ser feita com o AMFPHP, é dizer a ele aonde está os services, que usa para mandar os VO’s para o PHP, e aonde se encontra o package dos VO’s, que ele usa para serializar os VO’s Flex e PHP.

Para isso, abra o arquivo globals.php dentro da pasta do AMFPHP e deixe assim:

*Coloque a tag do php no inicio e no fim.
[php]

//This file is intentionally left blank so that you can add your own global settings
    //and includes which you may need inside your services. This is generally considered bad
    //practice, but it may be the only reasonable choice if you want to integrate with
    //frameworks that expect to be included as globals, for example TextPattern or WordPress

//Set start time before loading framework
    list($usec, $sec) = explode(” “, microtime());
    $amfphp[‘startTime’] = ((float)$usec + (float)$sec);

$servicesPath = “../../application/services/”;
    $voPath = “../../application/business/vo/”;

//As an example of what you might want to do here, consider:
    /*
    if(!PRODUCTION_SERVER)
    {
        define(“DB_HOST”, “localhost”);
        define(“DB_USER”, “root”);
        define(“DB_PASS”, “”);
        define(“DB_NAME”, “amfphp”);
    }
    */

[/php]

Perceba as variaveis $servicesPath e $voPath.

É preciso configurar os sources_paths do projeto no caso o src_flex e src_php, para isso:

No seu projeto de um botão direito -> Properties -> Selecione a opção Flex Build Path -> clique no botão Add Folder e procure a pasta src_php -> Em Main source folder selecione a pasta src_flex.

Esta tela deverá ficar assim:

Flex Build Path
Listagem 3

E para concluir, precisamos informar ao compilador Flex qual o endereço do gateway onde será possível trocar dados em cima do protocolo AMF3, para isso gere um arquivo com o nome de     services-config.xml  na raiz da pasta src_flex  com este conteúdo:

XML

   1: <services-config>
   2:     <services>
   3:         <service id="amfphp-flashremoting-service"
   4:             class="flex.messaging.services.RemotingService"
   5:                 messageTypes="flex.messaging.messages.RemotingMessage">
   6:             <destination id="amfgateway">
   7:                 <channels>
   8:                     <channel ref="channel-amf"/>
   9:                 </channels>
  10:                 <properties>
  11:                     <scope>session</scope>
  12:                     <source>*</source>
  13:                 </properties>
  14:             </destination>
  15:         </service>
  16:     </services>
  17:     <channels>
  18:         <channel-definition id="channel-amf" class="mx.messaging.channels.AMFChannel">
  19:             <endpoint uri="http://{server.name}:{server.port}/FlexPHP/libs/amfphp/gateway.php"
  20:                 class="flex.messaging.endpoints.AMFEndpoint"/>
  21:         </channel-definition>
  22:     </channels>
  23: </services-config>

E nos Properties do Projeto, o FlexCompiler deverá ficar assim:

Flex Compiler

Listagem 4

Detalhando as Camadas

O Fluxo das Camada é a seguinte:

O Flex chama um Serviço através do AMFPHP que direciona para uma classe com um especifico método no package services;

Ex: O Flex Chama a classe ContatoService, solicitando o método  save(), passando por parâmentro uma instância de ContatoVO.

A Service chama uma classe da Facade  com o respectivo método solicitado;

Ex: O ContatoService chama o ContatoFacade solicitando o método save() passando por parâmentro uma instância de ContatoVO.

A Facade abre uma transação, e chama um SessionBean;

Ex: O ContatoFacade  chama o ContatoBean solicitando o método save() passando por parâmentro uma instância de ContatoVO.

O SessionBean faz a regra de negócio específica do caso de uso,  e se tudo tiver ok chama um EntityBean para fazer a persistência, se não dispara uma nova Exception dando rollback no banco e mostrando uma mensagem de erro para o Flex através do catch na Facade;

Ex: O ContatoSession chama o ContatoBean solicitando para que insira ou atualize os dados através do ContatoVO  passado por parâmentro.

Tendo conhecimento do Fluxo das camadas pode se observar que o código ficou bem separado, o que garante baixo acoplamento e alta coesão.

E como Fica no Flex?

Estrutura de Pastas Flex 
Listagem 5

Como este exemplo tem por finalidade de mostrar uma proposta de arquitetura com Flex e PHP, este exemplo não adota padrões de projetos no lado Flex, mas é extremamente recomendável o uso de Padrões seja com o Cairngorm da Adobe ou tantos outros existentes porae.

A classe RemoteConnection é uma classe que tem por finalidade de abstrair o uso do RemoteObject, como por exemplo você pode chamar o ContatoService desta forma:

[as]

var contatoVO:ContatoVO = new ContatoVO();
contatoVO.dsNome     = txtNome.text;
contatoVO.dsEmail    = txtEmail.text;
contatoVO.nuTelefone = txtTelefone.text;
contatoVO.dsCidade   = txtCidade.text;
contatoVO.dsEstado   = txtEstado.text;
contatoVO.dsMensagem = txtMensagem.text;

RemoteConnection.call(“ContatoService”,”save”,
     function(event:ResultEvent):void
     {
         Alert.show(“Email enviado com sucesso!”,”SUCESSO!”);
         clear();       
    },
    contatoVO
);

[/as]

Perceba que gero um VO com as informações da Tela, e Solicito o serviço ContatoService chamando o método save() passando por parâmetro uma instância de ContatoVO.

A Função de retorno implementei dentro do próprio método, mas eu poderia criar uma função só para tratar o retorno do método assíncrono.

Bom Senhores, acredito que consegui dar uma boa explicação sobre como trabalhar arquiteturalmente com Flex e PHP.

Estarei diponibilizando o projeto usado no exemplo, para executar, dentro da pasta docs contém 2 arquivos, um chamado localhost.sql.zip que pode ser usado para gerar o banco de dados e outro chamado MER.xml que é o MER feito com o DBDesigner. Após gerar o banco, é só importar no seu Flex Builder 3.

Aplicação Rodando

FlexPHP

Source do Projeto: Projeto FlexPHP

Para aqueles que tiverem dúvidas, sujestões ou críticas podem entrar em contato comigo, na medida do possível estarei lhes respondendo.

Obrigado a Todos e um Bom Proveito!

Liz.. te amo querida! =*

36 thoughts on “Proposta de Arquitetura com Adobe Flex e PHP usando Zend Framework

  1. Mário Júnior

    Parabéns Rodrigo, muito bom!
    Graças a Deus, o paradigma da OOP vem se fortalecendo muito no mundo PHP, no meu tempo, era pecado usar OOP no php4.. hehehe.

    Só tenho uma pqna ressalva, mas q vale a análise de cada caso de uso: o framework.

    Acho o Zend um framework muito grande até para projetos de médio porte. Talvez vc conseguisse simplificar muito aplicando o conceito de MVC mais puramente e com um DAO genérico, ou até mesmo usar um ORM como o Lumine que simplifica bastante o lado do PHP.

    Mas como disse antes, vale a análise de cada caso, se o projeto realmente for grande, daí o uso do Zend Framework vale a pena.

    Abraços, e novamente parabéns cara.

    Like

    Reply
  2. Daniel Schmitz

    Eu concordo com o Mário, talvez o Zend seja um tiro de bazuka numa mosca…

    Aqui o cakePHP nao te atendeu nao ?

    ou quem sabe o RoR 🙂

    Like

    Reply
  3. Karunya

    Hi ,

    I have been really looking for FLEX AND SPRING , HIBERNATE samples to work with, but I don’t understand the languge would it be possible to have english version.

    thanks

    Like

    Reply
  4. Rodrigo Pereira Fraga

    Hi!

    In my blog, I only posted integrating
    AdobeFlex + ZendFramework + AMFPHP.

    It few days, I will post an article integrating
    AdobeFlex + BlazeDS + Hibernate + SpringFramework.

    But at the time, what do you really have doubt?

    Like

    Reply
  5. Rodrigo Pereira Fraga

    Dante…
    Só um detalhe, Flex não é Flash! na verdade não tem nada haver mesmo!

    Eu mesmo não gosto do timeline do Flash nem sei mecher direito naquilo…

    Mas amo programar orientado a objetos com Flex!

    Abraços
    o/

    Like

    Reply
  6. Dante

    Sim. Flex não é Flash, mas usa o plugin do tal…
    Para o usuário final é um Flash.

    Veja como seu exemplo ficou aqui no meu IE 7 64bits que não tem suporte ao Plugin do Flash ainda.

    Alternate HTML content should be placed here. This content requires the Adobe Flash Player. Get Flash

    Like

    Reply
  7. Pingback: Tony Ngo » Blog Archive » Zend Framework and AMFPHP

  8. Pingback: Manifesto Flex brasil - Rodrigo Fraga - RIA Evangelist

  9. Cláudio

    mano, gostei demais de sua aplicacao, so nao consegui baixar o codigo fonte para estudo, sou novato em flex, poderia me consguir um link pra baixar, este do site da erro 404…

    Like

    Reply
  10. Paulo

    Rodrigo, grande artigo. Como iniciante em flex, deu uma grande forca. Nao consegui abrir o link do exemplo. Tem o source pra envio ou link pra download.

    Grande forca e obrigado

    Like

    Reply
  11. Márcio

    Realmente, muito bom! Usar Design Patterns sempre é bom. Poderia me enviar, ou disponibilizar o source?

    Grato e Parabéns!

    Like

    Reply
  12. Ricardo G.

    @Rodrigo Pereira Fraga

    Tenho que discordar com você.
    Trabalhei com Flash por 3 anos, e agora com Flex 2/3 por 2 anos.

    E ambos são a mesma coisa.
    Claro, muda totalmente a forma de programar (um tem a timeline que você odeia, e outro usa o drag n’ drop de componentes) mas ambos são iguais…

    A linguagem é a mesma, e o que você consegue fazer em um, teoricamente consegue fazer no outro também. Algumas coisas com mais trabalho, outras com menos.

    Like

    Reply
  13. Giolvani

    olá Rodrigo!

    vc poderia disponibilizar o código pra download, pois nao estou conseguindo baixar o mesmo!!!

    e uma dica,
    vc poderia fazer o mesmo exemplo usando a nova versao do zf que agora ja vem com o amfphp incluso…

    abraços
    e parabéns pelo blog

    Like

    Reply
  14. Aécio cleber

    Bom quem Odeia o Flesh é porque não conhece o programa, é a coisa mais completa que já criaram, da para programar, da para desenhar, da para animar, o flesh só volta comprar pão.
    mas tem gente que tem medo da interface do programa oO. ou tem ódio de design!

    Like

    Reply
  15. dimitrikx

    Muito legal, esta me ajudando em meu inicio de integracao do php com o flex.
    mesmo sabendo que não pretendo criar um formulario de contato no flex.
    valew

    Like

    Reply
  16. Rafael Silveira

    Acho que a maior (e melhor) vantagem do Flex em Relação ao Flash é o preço! xD

    Já sobre o ZF, discordo de quem disse que é exagero usa-lo em pequenos/medios projetos.

    Até por que na versão atual, fica muito fácil criar webservice tanto usando AMF quanto SOAP/WSDL sem precisar alterar as classes dos serviços.

    Vale a pena dar uma conferida na nova versão!

    E muito legal seu artigo, algumas coisas eu prefiro fazer de uma outra forma, mas sempre é bom conhecer outras formas de criar.

    Like

    Reply
  17. blog home

    Resources similar to the one you described here is going to be very beneficial to me personally! I will post a website link to this web page on my weblog. Read my website visitors will find that really beneficial.

    Like

    Reply
  18. commercial hard money loans

    Thank you for that wise critique. Me & my neighbour were preparing to do some research about that. We got a good book on that matter from our local library and most books where not as influensive as your information and facts. I’m quite glad to see this kind of information and facts which I was searching for a long time.

    Like

    Reply
  19. Shanae Mcsparren

    Hey Yawl I read the information you posted here and I wanted to say you guys need to continue to add more content. It’s extremely interesting to us readers and I will probably be back. I will write about with my friends. Keep it rolling!

    Like

    Reply

Leave a comment