| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.amf.server">
- <title>Zend_Amf_Server</title>
- <para>
- <classname>Zend_Amf_Server</classname> fornece um servidor no estilo <acronym>RPC</acronym>
- para manipular requisições feitas com Adobe Flash Player usando o protocolo
- <acronym>AMF</acronym>. Como todas as classes de servidor do Zend Framework, ela segue a
- <acronym>API</acronym> SoapServer, fornecendo uma interface fácil de lembrar para criar
- servidores.
- </para>
- <example id="zend.amf.server.basic">
- <title>Servidor AMF Básico</title>
- <para>
- Vamos assumir que você tenha criado uma classe <classname>Foo</classname> com uma
- variedade de métodos públicos. Você pode criar um servidor <acronym>AMF</acronym> usando
- o código a seguir:
- </para>
- <programlisting language="php"><![CDATA[
- $server = new Zend_Amf_Server();
- $server->setClass('Foo');
- $response = $server->handle();
- echo $response;
- ]]></programlisting>
- <para>
- Alternativamente, você pode optar por atribuir uma simples função como chamada de
- retorno:
- </para>
- <programlisting language="php"><![CDATA[
- $server = new Zend_Amf_Server();
- $server->addFunction('myUberCoolFunction');
- $response = $server->handle();
- echo $response;
- ]]></programlisting>
- <para>
- Você também pode misturar e combinar várias classes e funções. Quando fizer isso,
- sugerimos que utilize namespaces para que nenhuma colisão de nomes de métodos ocorra;
- isso pode ser feito simplesmente passando uma string como segundo argumento, tanto para
- <methodname>addFunction()</methodname> ou <methodname>setClass()</methodname>.
- </para>
- <programlisting language="php"><![CDATA[
- $server = new Zend_Amf_Server();
- $server->addFunction('myUberCoolFunction', 'my')
- ->setClass('Foo', 'foo')
- ->setClass('Bar', 'bar');
- $response = $server->handle();
- echo $response;
- ]]></programlisting>
- <para>
- O <classname>Zend_Amf_Server</classname> também permite que serviços sejam
- dinamicamente carregados baseado em um caminho de diretório fornecido. Você pode
- adicionar tantos quantos diretórios desejar ao servidor. A ordem em que você adiciona os
- diretórios ao servidor será a ordem em que a pesquisa <acronym>LIFO</acronym> será
- realizada nos diretórios para encontrar a classe. Adição de diretórios é feita com
- o método <methodname>addDirectory()</methodname>.
- </para>
- <programlisting language="php"><![CDATA[
- $server->addDirectory(dirname(__FILE__) .'/../services/');
- $server->addDirectory(dirname(__FILE__) .'/../package/');
- ]]></programlisting>
- <para>
- Ao chamar serviços remotos, os nomes de seus fontes podem conter sublinhados ("_") e
- pontos (".") como delimitadores de diretórios. Quando um sublinhado é usado, as
- conveções <acronym>PEAR</acronym> e Zend Framework para nomenclaturas serão respeitadas.
- Isso significa que se você chamar um serviço <filename>com_Foo_Bar</filename> o servidor
- procurará pelo arquivo <filename>Bar.php</filename> em cada caminho incluído em
- <filename>com/Foo/Bar.php</filename>. Se a notação de ponto é usada para seu serviço
- remoto como em <filename>com.Foo.Bar</filename>, <filename>com/Foo/Bar.php</filename>
- será adicionado ao final de cada caminho incluído para autocarregar
- <filename>Bar.php</filename>
- </para>
- <para>
- Todas as requisições <acronym>AMF</acronym> enviadas ao script serão manipuladas
- posteriormente pelo servidor, e uma resposta <acronym>AMF</acronym> será retornada.
- </para>
- </example>
- <note>
- <title>
- Todas as Funções e Métodos atribuídos precisam de Blocos de Documentação (Docblocks)
- </title>
- <para>
- Como todos os componentes de servidor no Zend Framework, você precisa documentar seus
- métodos de classe usando docblocks <acronym>PHP</acronym>. Você precisa fornecer,
- no mínimo, anotações para cada argumento obrigatório assim como o valor de retorno.
- Exemplo:
- </para>
- <programlisting language="php"><![CDATA[
- // Função para atribuição:
- /**
- * @param string $name
- * @param string $greeting
- * @return string
- */
- function helloWorld($name, $greeting = 'Hello')
- {
- return $greeting . ', ' . $name;
- }
- ]]></programlisting>
- <programlisting language="php"><![CDATA[
- // Classe atribuída
- class World
- {
- /**
- * @param string $name
- * @param string $greeting
- * @return string
- */
- public function hello($name, $greeting = 'Hello')
- {
- return $greeting . ', ' . $name;
- }
- }
- ]]></programlisting>
- <para>
- Outras anotações podem ser usadas, mas serão ignoradas.
- </para>
- </note>
- <sect2 id="zend.amf.server.flex">
- <title>Conectando ao servidor com Flex</title>
- <para>
- Conectar a seu <classname>Zend_Amf_Server</classname> a partir de seu projeto Flex é
- bem simples; você simplesmente precisa apontar sua <acronym>URI</acronym> de ponto de
- extremidade (endpoint) para seu script <classname>Zend_Amf_Server</classname>
- </para>
- <para>
- Digamos, por exemplo, que você tenha criado seu servidor e o colocado no arquivo
- <filename>server.php</filename> na raiz de sua aplicação, e seu <acronym>URI</acronym> é
- <filename>http://example.com/server.php</filename>. Neste caso, você modificaria seu
- arquivo <filename>services-config.xml</filename> para definir o atributo uri de ponto de
- extremidade, <property>channel</property>, para este valor.
- </para>
- <para>
- Se você nunca criou um arquivo <filename>services-config.xml</filename> você poderá
- fazê-lo abrindo seu projeto na janela 'Navigator' do Flex Builder. Clique com o botão
- direito sobre nome do projeto e selecione 'properties'. Na janela de diálogo de
- propriedades do projeto vá para o menu 'Flex Build Path', aba 'Library path' e tenha
- certeza de que o arquivo '<filename>rpc.swc</filename>' foi adicionado aos caminhos de
- seus projetos e pressione 'Ok' para fechar a janela.
- </para>
- <para>
- Você também precisará informar ao compilador para usar o arquivo
- <filename>services-config.xml</filename> para encontrar o ponto de extremidade do
- <classname>RemoteObject</classname>. Para isso, abra novamente o painel de propriedades
- de seu projeto clicando com o botão direito do mouse no diretório do projeto a partir
- da janela 'Navigator' e selecionando 'properties'. Na popup de propriedades selecione
- 'Flex COmpiler' e adicione a seqüência de caracteres:
- <command>-services "services-config.xml"</command>. Pressione 'Apply' e depois 'OK' para
- voltar e atualizar a opção. O que você acabou de fazer foi dizer ao compilador Flex para
- procurar por variáveis de tempo de execução no arquivo
- <filename>services-config.xml</filename> que serão usadas pela classe
- <classname>RemoteObject</classname>
- </para>
- <para>
- Agora precisamos dizer ao Flex qual arquivo de configuração de serviços usar para
- conectar a nossos métodos remotos. Por essa razão crie um novo arquivo
- '<filename>services-config.xml</filename>' em seu diretório <filename>src</filename> do
- seu projeto Flex. Pra fazer isso clique com o botão direito no diretório do projeto e
- selecione 'new'; 'File' que uma nova janela se abrirá. Selecione o diretório do projeto
- e nomeie o arquivo '<filename>services-config.xml</filename>' e pressione 'finish'.
- </para>
- <para>
- O Flex criou um novo <filename>servies-config.xml</filename> e o abriu. Use o texto de
- exemplo a seguir para seu arquivo <filename>services-config.xml</filename>. Tenha
- certeza de atualizar seu ponto de extremidade (endpoint) para coincidir com seu servidor
- de testes e que você salve o arquivo.
- </para>
- <programlisting language="xml"><![CDATA[
- <?xml version="1.0" encoding="UTF-8"?>
- <services-config>
- <services>
- <service id="zend-service"
- class="flex.messaging.services.RemotingService"
- messageTypes="flex.messaging.messages.RemotingMessage">
- <destination id="zend">
- <channels>
- <channel ref="zend-endpoint"/>
- </channels>
- <properties>
- <source>*</source>
- </properties>
- </destination>
- </service>
- </services>
- <channels>
- <channel-definition id="zend-endpoint"
- class="mx.messaging.channels.AMFChannel">
- <endpoint uri="http://example.com/server.php"
- class="flex.messaging.endpoints.AMFEndpoint"/>
- </channel-definition>
- </channels>
- </services-config>
- ]]></programlisting>
- <para>
- Há dois pontos chave no exemplo. Primeiro, mas por último na listagem, criamos um canal
- <acronym>AMF</acronym> e especificados o poonto de extremidade (endpoint) como
- <acronym>URL</acronym> para nosso <classname>Zend_Amf_Server</classname>:
- </para>
- <programlisting language="xml"><![CDATA[
- <channel-definition id="zend-endpoint"
- <endpoint uri="http://example.com/server.php"
- class="flex.messaging.endpoints.AMFEndpoint"/>
- </channel-definition>
- ]]></programlisting>
- <para>
- Note que demos a este canal um identificador, "zend-endpoint". O exemplo cria um destino
- de serviço que se refere a este canal, atribuindo a ele um ID também - neste caso
- "zend".
- </para>
- <para>
- Em nossos arquivos <acronym>MXML</acronym> do Flex, precisamos ligar um
- <classname>RemoteObject</classname> ao serviço. Em <acronym>MXML</acronym>, isto é feito
- como a seguir:
- </para>
- <programlisting language="xml"><![CDATA[
- <mx:RemoteObject id="myservice"
- fault="faultHandler(event)"
- showBusyCursor="true"
- destination="zend">
- ]]></programlisting>
- <para>
- Aqui, definimos um novo objeto remoto identificado por "myservice" ligado ao destino de
- serviço "zend" que definimos no arquivo <filename>services-config.xml</filename>. Nós
- depois chamamos métodos em nosso ActionScript simplesmente
- chamando "myservice.<método>". Como no exemplo:
- </para>
- <programlisting language="ActionScript"><![CDATA[
- myservice.hello("Wade");
- ]]></programlisting>
- <para>
- Quando usando espaços de nomes (namespaces), usamos:
- "myservice.<espaço de nome>.<método>":
- </para>
- <programlisting language="ActionScript"><![CDATA[
- myservice.world.hello("Wade");
- ]]></programlisting>
- <para>
- Para mais informações sobre como utilizar o <classname>RemoteObject</classname> do Flex,
- <ulink url="http://livedocs.adobe.com/flex/3/html/help.html?content=data_access_4.html">
- visite o site da Ajuda do Adobre Flex 3</ulink>.
- </para>
- </sect2>
- <sect2 id="zend.amf.server.errors">
- <title>Manipulação de Erros</title>
- <para>
- Por padrão, todas as exceções lançadas em suas classes ou funções anexadas serão obtidas
- e retornadas como <classname>ErrorMessage</classname>s do <acronym>AMF</acronym>.
- No entando, o conteúdos destes objetos <classname>ErrorMessage</classname> variam se
- o servidor está ou não em modo de "produção" (o estado padrão).
- </para>
- <para>
- Quando em modo de produção, somente o código da exceção será retornado. Se você
- desabilitar o modo de produção - algo que você deve fazer apenas para testes - a maioria
- dos detalhes de exceção serão retornados: a mensagem de exceção, linha, e
- pilha de execução (backtrace) serão todos anexados.
- </para>
- <para>
- Para desabilitar o modo de produção, faça o seguinte:
- </para>
- <programlisting language="php"><![CDATA[
- $server->setProduction(false);
- ]]></programlisting>
- <para>
- Para habilitá-lo novamnete, passe um valor booleano <constant>TRUE</constant>:
- </para>
- <programlisting language="php"><![CDATA[
- $server->setProduction(true);
- ]]></programlisting>
- <note>
- <title>Desabilite o modo de produção com moderação!</title>
- <para>
- Recomendamos desabilitar o modo de produção somente durante o desenvolvimento.
- Mensagens de exceção e pilhas de execução podem conter informações sensíveis que
- você provavelmente não deseje que terceiros tenham acesso. Mesmo
- <acronym>AMF</acronym> sendo um formato binário, a especificação é aberta, o que
- quer dizer que qualquer um pode, potencialmente, desserializar os dados carregados.
- </para>
- </note>
- <para>
- Uma área para ser especialmente cuidadoso são os próprios erros <acronym>PHP</acronym>.
- Quando a diretiva <property>display_errors</property> do <acronym>INI</acronym> está
- habilitada, qualquer erro <acronym>PHP</acronym> para o nível atual de reltório de erros
- são mostrados diretamente na saída - potencialmente interrompendo a carga de dados
- <acronym>AMF</acronym>. Sugerimos desabilitar a diretiva
- <property>display_errors</property> em modo de produção para evitar tais problemas
- </para>
- </sect2>
- <sect2 id="zend.amf.server.response">
- <title>Respostas AMF</title>
- <para>
- Ocasionalmente você pode desejar manipular levemente o objeto de resposta, tipicamente
- para retornar cabeçalhos de mensagem extra. O método <methodname>handle()</methodname>
- do servidor retorna o objeto da resposta, possibilitando a você fazer isto.
- </para>
- <example id="zend.amf.server.response.messageHeaderExample">
- <title>Adicionando Cabeçalhos de Mensagem à Resposta AMF</title>
- <para>
- Neste exemplo, adicionamos um <classname>MessageHeader</classname> 'foo' com o
- valor 'bar' à resposta antes de retorná-la.
- </para>
- <programlisting language="php"><![CDATA[
- $response = $server->handle();
- $response->addAmfHeader(new Zend_Amf_Value_MessageHeader('foo', true, 'bar'))
- echo $response;
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.amf.server.typedobjects">
- <title>Objetos Tipados</title>
- <para>
- De modo similar ao <acronym>SOAP</acronym>, <acronym>AMF</acronym> permite que sejam
- passados objetos entre o cliente e o servidor. Isso permite uma grande quantidade de
- flexibilidade e coerência entre os dois ambientes.
- </para>
- <para>
- <classname>Zend_Amf</classname> fornece três métodos para mapeamento entre objetos
- ActionScript e <acronym>PHP</acronym>.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Primeiro, você deve criar explicitamente ligações no nível do servidor, usando o
- método <methodname>setClassMap()</methodname>. O primeiro argumento é o nome da
- classe ActionScript, o segundo é a classe <acronym>PHP</acronym> que a mapeia:
- </para>
- <programlisting language="php"><![CDATA[
- // Mapeia a classe ActionScript 'ContactVO' para a classe PHP 'Contact':
- $server->setClassMap('ContactVO', 'Contact');
- ]]></programlisting>
- </listitem>
- <listitem>
- <para>
- Em segundo lugar, você definir a propriedade pública
- <varname>$_explicitType</varname> em sua classe <acronym>PHP</acronym>, com o
- valor representando a classe ActionScript para mapear:
- </para>
- <programlisting language="php"><![CDATA[
- class Contact
- {
- public $_explicitType = 'ContactVO';
- }
- ]]></programlisting>
- </listitem>
- <listitem>
- <para>
- Terceiro, de maneira similar, você pode definir o método público
- <methodname>getASClassName()</methodname> em sua classe <acronym>PHP</acronym>;
- este método deve retornar a classe ActionScript apropriada:
- </para>
- <programlisting language="php"><![CDATA[
- class Contact
- {
- public function getASClassName()
- {
- return 'ContactVO';
- }
- }
- ]]></programlisting>
- </listitem>
- </itemizedlist>
- <para>
- Embora tenhamos criado o ContactVO no servidor precisamos agora fazer a classe
- correspondente em <acronym>AS3</acronym> para que o objeto de servidor seja mapeado.
- </para>
- <para>
- Clique com o botão direito na pasta <filename>src</filename> de seu projeto Flex e
- selecione 'New' -> 'ActionScript File'. Nomeie o arquivo como 'ContactVO' e pressione
- 'finish' para ver o novo arquivo. Copie o seguinte código para finalizar a criação da
- classe.
- </para>
- <programlisting language="as"><![CDATA[
- package
- {
- [Bindable]
- [RemoteClass(alias="ContactVO")]
- public class ContactVO
- {
- public var id:int;
- public var firstname:String;
- public var lastname:String;
- public var email:String;
- public var mobile:String;
- public function ContactVO():void {
- }
- }
- }
- ]]></programlisting>
- <para>
- A classe é sintaticamente equivalente à classe <acronym>PHP</acronym> com o mesmo nome.
- Os nomes de variáveis são exatamente os mesmos e precisam estar sob o mesmo caso para
- que funcione apropriadamente. Existem duas marcações meta (meta tags)
- <acronym>AS3</acronym> únicas nesta classe. A primeira é Bindable, que faz com
- que um evento de alteração (change) seja disparado quando ela é atualizada. A segunda
- marcação é RemoteClass, que define que esta classe pode ter um objeto remoto mapeado a
- ela com um apelido, neste caso <emphasis>ContactVO</emphasis>. É obrigatório que o valor
- desta marcação seja definido seja estritamente equivalente ao da classe
- <acronym>PHP</acronym>.
- </para>
- <programlisting language="as"><![CDATA[
- [Bindable]
- private var myContact:ContactVO;
- private function getContactHandler(event:ResultEvent):void {
- myContact = ContactVO(event.result);
- }
- ]]></programlisting>
- <para>
- O evento de resultado gerado pela chamada ao serviço é instantaneamente convertido para
- o ContactVO do Flex. Qualquer coisa que seja direcionada a <varname>myContact</varname>
- será atualizado e os dados de ContactVO serão retornados.
- </para>
- </sect2>
- <sect2 id="zend.amf.server.resources">
- <title>Recursos</title>
- <para>
- <classname>Zend_Amf</classname> fornece ferramentas para mapear tipos de recursos
- retornados por classes de serviços em informações consumíveis pelo ActionScript.
- </para>
- <para>
- A fim de lidar com tipo de recurso específico, o usuário precisa criar uma classe plugin
- chamado após o nome do recurso, com palavras em maiúsculas e espaços removidos (assim
- recurso do tipo "resultado mysql" torna-se ResultadoMysql), com algum prefixo, ex.:
- <classname>Meu_ResultadoMysql</classname>. Esta classe precisa implementar um método,
- <methodname>parse()</methodname>, recebendo um argumento - o recurso - e retornando o
- valor a ser enviado para o ActionScript. A classe deve estar localizada no arquivo
- chamado após o nome do componente, ex.: <filename>ResultadoMysql.php</filename>.
- </para>
- <para>
- O diretório contendo os plugins para manipulação de recursos devem ser registrados com o
- carregador de tipo <classname>Zend_Amf</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- Zend_Amf_Parse_TypeLoader::addResourceDirectory(
- "Meu",
- "application/library/recursos/Meu"
- );
- ]]></programlisting>
- <para>
- Para uma discussão detalhada sobre o plugins carregadores, por favor veja a seção
- <link linkend="zend.loader.pluginloader">plugin carregador</link>.
- </para>
- <para>
- O diretório padrão para recursos <classname>Zend_Amf</classname> é registrado
- automaticamente e atualmente contém manipuladores para recursos "resultado mysql" e
- "stream".
- </para>
- <programlisting language="php"><![CDATA[
- // Classe de exemplo implementando a manipulação de recursos do tipo "resultado mysql"
- class Zend_Amf_Parse_Recurso_ResultadoMysql
- {
- /**
- * Decodifica o recurso em uma matriz
- *
- * @param resource $resource
- * @return array
- */
- public function parse($resource) {
- $result = array();
- while($row = mysql_fetch_assoc($resource)) {
- $result[] = $row;
- }
- return $result;
- }
- }
- ]]></programlisting>
- <para>
- Ao tentar retornar um tipo desconhecido de recirso (ex., um para o qual não haja plugin
- manipulador existente) resultará em uma exceção.
- </para>
- </sect2>
- <sect2 id="zend.amf.server.flash">
- <title>Conectando ao Servidor a partir do Flash</title>
- <para>
- Conectando ao seu <classname>Zend_Amf_Server</classname> a partir de seu projeto Flash é
- ligeiramente diferente do que com Flex. Contudo, depois da conexão, Flash funciona com
- <classname>Zend_Amf_Server</classname> da mesma forma que com Flex. O exemplo a seguir
- também pode ser usado com um arquivo <acronym>AS3</acronym> do Flex. Reutilizaremos a
- mesma configuração <classname>Zend_Amf_Server</classname> com a classe Mundo para nossa
- conexão.
- </para>
- <para>
- Abra o Flash CS e crie um novo arquivo Flash (ActionScript 3). Nomeie o documento
- <filename>ExemploZend.fla</filename> e salve o documento em uma pasta que você usará
- para este exemplo. Crie uma nova classe <acronym>AS3</acronym> no mesmo diretório e
- nomeie o arquivo como <filename>Principal.as</filename>. Tenha ambos os arquivos abertos
- em seu editor. Vamos conectar os dois arquivos através da classe de documento. Selecione
- ExemploZend e clique no palco. No painel de propriedade dos palco, altere a classe de
- documento (Document class) para Principal. Isso ligará o arquivo ActionScript
- <filename>Principal.as</filename> com a interface do usuário do arquivo
- <filename>ExemploZend.fla</filename>. Quando você executa o arquivo Flash ExemploZend, a
- classe <filename>Principal.as</filename> será executada agora. Agora, vamos adicionar o
- código ActionScript para fazer a chamada <acronym>AMF</acronym>.
- </para>
- <para>
- Agora nós faremos a classe Principal de modo que possamos enviar dados ao servidor e
- exibir o resultado. Copie o código a seguir para seu arquivo
- <filename>Principal.as</filename> e depois vamos descrever, passo a passo, o papel de
- cada elemento nele.
- </para>
- <programlisting language="as"><![CDATA[
- package {
- import flash.display.MovieClip;
- import flash.events.*;
- import flash.net.NetConnection;
- import flash.net.Responder;
- public class Principal extends MovieClip {
- private var gateway:String = "http://exemplo.com/server.php";
- private var connection:NetConnection;
- private var responder:Responder;
- public function Principal() {
- responder = new Responder(onResult, onFault);
- connection = new NetConnection;
- connection.addEventListener(NetStatusEvent.NET_STATUS, onComplete);
- connection.connect(gateway);
- }
- public function onComplete( e:NetStatusEvent ):void {
- if(e.info.code == "NetGroup.Connect.Succcess") {
- var params = "Sent to Server";
- connection.call("Mundo.alo", responder, params);
- }
- }
- private function onResult(result:Object):void {
- // Display the returned data
- trace(String(result));
- }
- private function onFault(fault:Object):void {
- trace(String(fault.description));
- }
- }
- }
- ]]></programlisting>
- <para>
- Primeiro precisamos importar duas bibliotecas ActionScriot que executam a maior parte do
- trabalho. A primeira é NetConnection que atua como um tubo bi-direcional entre o cliente
- e o servidor. A segunda é o objeto Responder, que manipula os valores de retorno do
- servidor relacionados ao sucesso ou falha da chamada.
- </para>
- <programlisting language="as"><![CDATA[
- import flash.net.NetConnection;
- import flash.net.Responder;
- ]]></programlisting>
- <para>
- Na classe, precisamos de três variáveis para representar a NetConnection, Responder e a
- <acronym>URL</acronym> da porta de entrada (gateway) para nossa instalação
- <classname>Zend_Amf_Server</classname>.
- </para>
- <programlisting language="as"><![CDATA[
- private var gateway:String = "http://exemplo.com/server.php";
- private var connection:NetConnection;
- private var responder:Responder;
- ]]></programlisting>
- <para>
- No contrutor de Principal criamos um respondedor e uma nova conexão ao
- ponto de extremidade (gateway) <classname>Zend_Amf_Server</classname>. O respondedor
- define dois métodos diferentes para manipular as respostas do servidor. Por simplicidade
- eles foram chamados de onResult e onFault.
- </para>
- <programlisting language="as"><![CDATA[
- responder = new Responder(onResult, onFault);
- connection = new NetConnection;
- connection.addEventListener(NetStatusEvent.NET_STATUS, onComplete);
- connection.connect(gateway);
- ]]></programlisting>
- <para>
- Na função onComplete, que é executada assim que o construtor tenha sido terminado, nós
- enviamos dados ao servidor. Precisamos adicionar mais uma linha que realiza a chamada a
- função Mundo->alo do <classname>Zend_Amf_Server</classname>
- </para>
- <programlisting language="as"><![CDATA[
- connection.call("Mundo.alo", responder, params);
- ]]></programlisting>
- <para>
- Quando instanciamos a variável responder, definimos uma função onResult e onFault para
- manipular a resposta do servidor. Adicionamos esta função para um resultado de sucesso
- vindo do servidor. Um manipulador de eventos de sucesso é executado sempre que uma
- conexão é manipulada apropriadamente no servidor.
- </para>
- <programlisting language="as"><![CDATA[
- private function onResult(result:Object):void {
- // Mostra os dados retornados
- trace(String(result));
- }
- ]]></programlisting>
- <para>
- A função onFault é chamada se há uma resposta inválida vinda do servidor. Isso acontece
- quando há um erro no servidor, a <acronym>URL</acronym> para o servidor é inválida, o
- serviço remoto ou método não existe ou se há qualquer outro problema relacionado à
- conexão.
- </para>
- <programlisting language="as"><![CDATA[
- private function onFault(fault:Object):void {
- trace(String(fault.description));
- }
- ]]></programlisting>
- <para>
- Completamos então a inclusão do ActionScript para realizar a conexão remota. Executando
- o arquivo ExemploZend agora faz a conexão ao <classname>Zend_Amf</classname>. Numa
- revisão, você adicionou as variáveis necessárias para abrir uma conexão ao servidor
- remoto, definiu quais métodos devem ser usados em sua aplicação para receber respostas
- do servidor e finalmente exibido os dados retornados através da função
- <methodname>trace()</methodname>.
- </para>
- </sect2>
- <sect2 id="zend.amf.server.auth">
- <title>Autenticação</title>
- <para>
- <classname>Zend_Amf_Server</classname> permite que você especifique ganchos de
- autentcação e autorização para controlar acesso aos serviços. Isso é feito usando a
- infraestrutura fornecida pelos componentes
- <link linkend="zend.auth"><classname>Zend_Auth</classname></link> e
- <link linkend="zend.acl"><classname>Zend_Acl</classname></link>.
- </para>
- <para>
- Para definir autenticação, o usuário fornece um adaptador de autenticação extendendo a
- classe abstrata <classname>Zend_Amf_Auth_Abstract</classname>. O adaptador deve
- implementar o método <methodname>authenticate()</methodname> como qualquer outro
- <link linkend="zend.auth.introduction.adapters">adaptador de autenticação</link>.
- </para>
- <para>
- O adaptador deve utilizar as propriedades <emphasis>_username</emphasis> e
- <emphasis>_password</emphasis> da classe pai,
- <classname>Zend_Amf_Auth_Adapter</classname>, para autenticar. Estes valores são
- definidos pelo servidor usando o método <methodname>setCredentials()</methodname> antes
- da chamada à <methodname>authenticate()</methodname> se as credenciais forem recebidas
- nos cabeçalhos da requisição <acronym>AMF</acronym>.
- </para>
- <para>
- A identidade retornada pelo adaptador deve ser um objeto contendo a propriedade
- <property>role</property> para que o controle de acesso da <acronym>ACL</acronym>
- funcione.
- </para>
- <para>
- Se o resultado da autenticação não for bem sucedido, a requisição não é mais procesada e
- uma mensagem de falha é retornada contendo as razões da falha obtida do resultado.
- </para>
- <para>
- O adaptador é conectado ao servidor usando o método <methodname>setAuth()</methodname>:
- </para>
- <programlisting language="php"><![CDATA[
- $server->setAuth(new My_Amf_Auth());
- ]]></programlisting>
- <para>
- O controle de acesso é realizado usando um objeto <classname>Zend_Acl</classname>
- definido pelo método <methodname>setAcl()</methodname>:
- </para>
- <programlisting language="php"><![CDATA[
- $acl = new Zend_Acl();
- criarPermissoes($acl); // Cria a estrutura de permissões
- $server->setAcl($acl);
- ]]></programlisting>
- <para>
- Se o objeto <acronym>ACL</acronym> é definido e a classe sendo chamada define o método
- <methodname>initAcl()</methodname>, este método será chamado com o objeto
- <acronym>ACL</acronym> como um argumento. A classe depois cria regras
- <acronym>ACL</acronym> adicionais e retorna <constant>TRUE</constant>, ou retorna
- <constant>FALSE</constant> se nenhum controle de acesso for necessário para esta classe.
- </para>
- <para>
- Depois de a <acronym>ACL</acronym> ser definida, o servidor verificará se o acesso é
- permitido com o papel definido pela autenticação, sendo o recurso o nome da classe (ou
- <constant>NULL</constant> para chamadas de funções) e o privileǵio sendo o nome da
- função. Se nenhuma autenticação for fornecida, e se o papel
- <emphasis>anonymous</emphasis> foi definido, ele será usado, em outro caso o acesso será
- negado.
- </para>
- <programlisting language="php"><![CDATA[
- if($this->_acl->isAllowed($role, $class, $function)) {
- return true;
- } else {
- require_once 'Zend/Amf/Server/Exception.php';
- throw new Zend_Amf_Server_Exception("Accesso não permitido");
- }
- ]]></programlisting>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|