Adobe Flex com PHP usando ZendAMF – primeiros passos

banner_announcement
Não é novidade o apoio da Adobe com tecnologias que se integrem perfeitamente com o Flex, A Zend, que mantém o PHP, tem no seu ZendFramework, um pacote chamado ZendAMF, para implementar essa integração entre o Flex e o PHP. Nas mãos de Wade Arnold, que também mantem o AMFPHP.
Demorei um certo tempo para começar a usar essa implementação, ja havia me acostumando com o AMFPHP e feito varios sistemas com ele. No entanto, a propría Adobe recomenda o uso do ZendAMF para construção de RIA's com Flex e PHP.
Como primeiro exemplo usando o ZendAMF, usarei o mesmo banco de dados feito no artigo anterior sobre Flex e Java.
Uma das vantagens do Flex foi idealizado para ser a camada de visão e isso permite que a camada de negócios fique transparente, podendo usar tanto Java, PHP ou .NET, precisando somente apontar para um endpoint diferente de acordo com sua necessidade.
Você pode baixar a ultima versão do ZendAMF no seguinte link. Detalhe importante, você não precisa baixar todo o ZendFramework para utilizar esse pacote.
Feito isso, descompacte os arquivos no diretorio de sua preferência, no meu caso, criei um chamado "ZendAmf" e certifique-se que contenha o diretorio "Zend".
O objetivo é não mudar quase em nada a forma de organização da qual era no AMFPHP. Portanto para testar o nosso AMF, vamos criar um arquivo chamado "gateway.php" contento o seguinte código:

PHP:
  1. <?php
  2. require_once 'Zend/Amf/Server.php';
  3. $server = new Zend_Amf_Server();
  4. $server->setProduction(false);
  5. echo($server->handle());
  6. ?>

Executando o link no seu navegador, deve aparecer a seguinte mensagem:

Zend Amf Endpoint

O ZendAMF esta pronto para nosso desenvolvimento, procurei manter a estrutura de diretorios o mais parecido possivel com o que já tinha feito no java, portanto, criaremos o seguinte diretorio para nosso VO; br.com.leonardofranca.vo e br.com.leonardofranca para a classe principal. A estrutura deve ficar da seguinte forma:

Zend
br/com/leonardofranca/vo
br/com/leonardofranca
gateway.php

O nosso VO no PHP ficaria da seguinte forma:

PHP:
  1. <?php
  2. class ContatosVO  
  3. {
  4.     public $_explicitType = 'br.com.leonardofranca.vo.ContatosVO';
  5.     public $id = 0;
  6.     public $nome = "";
  7.     public $email = "";
  8.    
  9.     function __construct()
  10.     {
  11.        
  12.     }
  13.    
  14.     public function getId()
  15.     {
  16.         return $this->id;
  17.     }
  18.    
  19.     public function setId($id)
  20.     {
  21.         $this->id = $id;
  22.     }
  23.    
  24.     public function getNome()
  25.     {
  26.         return $this->nome;
  27.     }
  28.    
  29.     public function setNome($nome)
  30.     {
  31.         $this->nome = $nome;
  32.     }
  33.    
  34.     public function getEmail()
  35.     {
  36.         return $this->email;
  37.     }
  38.    
  39.     public function setEmail($email)
  40.     {
  41.         $this->email = $email;
  42.     }
  43. }
  44. ?>

Em seguida, nossa classe principal, que efetuará as operações de listar, inserir, apagar e atualizar os dados do nosso banco:

PHP:
  1. <?php
  2. /*
  3.  * author Leonardo França
  4.  * site http://www.leonardofranca.com.br
  5.  */
  6. require_once 'vo/ContatosVO.php';
  7.  
  8. class Contatos  
  9. {
  10.     private $conexao;
  11.     private $sql;
  12.     private $query;
  13.     private $num;
  14.     private $dados;
  15.     public $contatosVO;
  16.    
  17.     function __construct()
  18.     {
  19.         $this->conexao = mysql_connect("localhost","root","");
  20.         mysql_select_db("java");
  21.     }
  22.    
  23.     public function getData()
  24.     {
  25.         $this->sql = "SELECT id, nome, email FROM tabela";
  26.         $this->query = mysql_query($this->sql);
  27.         $this->num = mysql_num_rows($this->query);
  28.         if ($this->num>0)
  29.         {
  30.             while ($this->row = mysql_fetch_assoc($this->query))
  31.             {
  32.                 $contatosVO = new ContatosVO();
  33.                 $contatosVO->setNome($this->row['nome']);
  34.                 $contatosVO->setEmail($this->row['email']);
  35.                 $contatosVO->setId($this->row['id']);
  36.                 $this->dados[] = $contatosVO;
  37.             }
  38.             return($this->dados);
  39.         }
  40.         else
  41.         {
  42.             return false;
  43.         }
  44.        
  45.     }
  46.    
  47.     public function insertData($contatosVO=ContatosVO)
  48.     {
  49.         $this->contatosVO = $contatosVO;
  50.         $this->sql = "INSERT INTO tabela (nome,email) VALUES
  51.         ('".$this->contatosVO->nome."',
  52.         '".$this->contatosVO->email."')";
  53.         $this->query = mysql_query($this->sql);
  54.         if (!mysql_error())
  55.         {
  56.             return true;
  57.         }
  58.         else
  59.         {
  60.             return false;
  61.         }
  62.     }
  63.    
  64.     public function deleteData($contatosVO=ContatosVO)
  65.     {
  66.         $this->contatosVO = $contatosVO;
  67.         $this->sql = "DELETE FROM tabela WHERE id = '".$this->contatosVO->id."' LIMIT 1";
  68.         $this->query = mysql_query($this->sql);
  69.         if (!mysql_error())
  70.         {
  71.             return true;
  72.         }
  73.         else
  74.         {
  75.             return false;
  76.         }
  77.     }
  78.    
  79.     public function updateData($contatosVO=ContatosVO)
  80.     {
  81.         $this->contatosVO = $contatosVO;
  82.         $this->sql = "UPDATE tabela SET nome = '".$this->contatosVO->nome."', email = '".$this->contatosVO->email."' WHERE id = '".$this->contatosVO->id."'";
  83.         $this->query = mysql_query($this->sql);
  84.         if (!mysql_error())
  85.         {
  86.             return true;
  87.         }
  88.         else
  89.         {
  90.             return false;
  91.         }
  92.     }
  93.    
  94. }
  95. ?>

Até aqui, nenhum misterio, temos uma classe simples que utiliza um objeto tipado, agora vamos editar o arquivo "gateway.php" para que possa chamar nosso vo e a classe de implementação:

PHP:
  1. <?php
  2. require_once 'Zend/Amf/Server.php';
  3. require_once 'br/com/leonardofranca/vo/ContatosVO.php';
  4. require_once 'br/com/leonardofranca/Contatos.php';
  5.  
  6. /** Bootstrap */
  7.  
  8. // Instantiate server
  9. $server = new Zend_Amf_Server();
  10. $server->setProduction(false);
  11. //$server->addDirectory('services/');
  12. // reflection
  13. $server->setClass('Contatos');
  14. $server->setClassMap('ContatosVO',"br.com.leonardofranca.vo.ContatosVO");
  15. // Handle request
  16. echo($server->handle());
  17. ?>

Adicionamos a chamada para nossa classe de implementação e mapeamos o vo, feito isto, vamos a parte mais dificil agora :P ,
pegamos o mesmo arquivo mxml do artigo anterior e modificaremos a seguinte linha:

MXML:
  1. <mx : RemoteObject id="ro" destination="zendamf" source="br.com.leonardofranca.Contatos" endpoint="http://localhost/ZendAmf/gateway.php">
  2. <!-- <mx : RemoteObject id="ro" destination="blazeds" source="br.com.leonardofranca.Contatos" endpoint="http://localhost:8080/Contatos/messagebroker/amf"> -->

De resto, não precisei modificar em nada a programação no Flex, o objetivo aqui foi mostrar de uma maneira simples, como podemos ter uma camada de visão rica com o Adobe Flex, independentemente da camada de negócios.

Download source

Mais sobre o ZendAMF:
http://wadearnold.com/blog/?page_id=155
http://framework.zend.com/download/amf
http://framework.zend.com/wiki/display/ZFPROP/Zend_Amf+-+Wade+Arnold

UPDATE

Nas ultimas versões do ZendAmf, é necessario alguns pacotes que constam no ZendFramework, uma opção é ir adicionando os pacotes no seu projeto ou usar todo o ZendFramework.

Recomendo os seguintes livros do meu amigo Daniel Pace Schmitz
Desenvolvendo Sistemas com Flex e PHP
Outros livros:
Flex 3 em Ação
Adobe Flex 3 Treinamento Direto da Fonte

Translations:
English Version

19 Comments

  • By Adriano, April 29, 2009 @ 16:36

    Muito elucidativo o trabalho. Obrigado.

  • By CalRaiden, May 4, 2009 @ 16:28

    Código fonte? teria como disponibilizar para download.
    =]

  • By Leonardo França, May 4, 2009 @ 23:36

    fonte disponibilizado ;)

  • By Leia Pimenta, June 9, 2009 @ 13:19

    Muito obrigado pelos esclarecimentos, embora eu ache que por mais que eu tenho estudado, menos eu sei.
    Um abraço!

  • By CalRaiden©, July 28, 2009 @ 11:18

    Interessante, mas já que está usando o zend, não seria interessante usar também a biblioteca DB do zend?

  • By Leonardo França, July 28, 2009 @ 15:24

    Sim, poderia usar perfeitamente, mas o objetivo foi mostrar que é possivel migrar o legado do AMFPHP sem problemas e sem dependencia do ZendFramework ;)

  • By Componentes Eletrônicos, October 20, 2009 @ 17:18

    Php zend é show, pena termos poucos certificados no BR , ainda sim vale estudar … parabéns pelo blog.

    Segue minha e-commerce: http://www.supertech-comp.com.br

  • By Luiz Barros, November 24, 2009 @ 17:51

    $this->dados[] = $contatosVO
    return($this->dados);

    Como eu posso usar os dados retornados preenchendo campos texto ?

    Alguem pode me ajudar

  • By Leonardo França, December 8, 2009 @ 11:59

    no cliente, vc vai usar assim:
    meutexto.text = re.message.body.nomedocampo

  • By Matheus, May 26, 2010 @ 15:51

    Toda vez que tento acessar o gateway.php, pelo wamp, ele coloca o arquivo pra ser feito o download. Não interpreta.
    Sabe alguma coisa que posso fazer?
    Abs

  • By Robinho, June 14, 2010 @ 15:46

    Ao executar o arquivo gateway.php é efetuado o download do mesmo. Poderia me ajudar?

    Obrigado!

  • By Wilson Neto, June 18, 2010 @ 09:16

    O mesmo acontece comigo, Ele pede para fazer download do gateway.php.

    Estou usando Wamp (php 5.2.8) e ZendAmf 1.10.5.

    Abraços

    Wilson

  • By Inacio, June 30, 2010 @ 14:44

    Localmente tudo esta perfeito.
    Ao publicar no meu dominio a app nao consegue encontrar endpoint. Mas se eu entre pelo navegador com endereco do endpoint aparece a mensagem ” Zend Amf Endpoint “. O problema sera que esta no dominio ou em alguma configuracao do apache ou php ?

    At. Inácio dos Santos

  • By Ved, July 11, 2010 @ 12:14

    Hey hey hey: me ajudou a encontrar um bug! Obrigado! o/

  • By Leonardo França, July 12, 2010 @ 14:00

    que bug vc achou Ved? vi que nas ultimas versões falta o arquivo Zend\Loader\Exception.php. Agora to com erro nos nomes dos pacotes que colocam em caixa alta

  • By clebio vieira, July 31, 2010 @ 17:01

    Oi Leonardo, segui todos os exemplos. Só que não está Cadastrando. Quando clico no botão atualizar ele não faz nada e no botão excluir ele diz que um item deve ser selecionado. O link com o gateway.php está ok. As classes PHP E AS devem estar na mesma pasta ? pq meu “projeto” ficou a parte Flex no meus documentos e a pasta output e os arquivos php tão dentro do WWW DO WAMP.
    SEGUE MEU CONSOLE: Code: 0
    Detail: #0 C:\wamp\www\ZendLeonardo\php\Zend\Amf\Server.php(550): Zend_Amf_Server->_dispatch(‘insertData’, Array, ‘br.com.leonardo…’)
    #1 C:\wamp\www\ZendLeonardo\php\Zend\Amf\Server.php(626): Zend_Amf_Server->_handle(Object(Zend_Amf_Request_Http))
    #2 C:\wamp\www\ZendLeonardo\php\gateway.php(17): Zend_Amf_Server->handle()
    #3 {main}
    String: Class “br_com_leonardofranca_Contatos” does not exist: Plugin by name ‘Br_com_leonardofranca_Contatos’ was not found in the registry; used paths:

  • By clebio vieira, July 31, 2010 @ 18:46

    RESOLVIDO: NO REMOTE OBJECTS ALTEREI DE:
    source=”br.com.leonardofranca.Contatos”
    PARA source=”Contatos”
    Agora está funcionado normalmente.
    abs…

  • By Leonardo França, August 1, 2010 @ 20:59

    esse é um bug que esta sendo trabalhado para ser resolvido na versao 1.11
    http://framework.zend.com/issues/browse/ZF-10174

Other Links to this Post

  1. Leonardo França » Adobe Flex with PHP using ZendAMF – first steps — August 24, 2010 @ 00:22

RSS feed for comments on this post. TrackBack URI

Leave a comment

WordPress Themes


Video & Audio Comments are proudly powered by Riffly