| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 17136 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.amf.server">
- <title>Zend_Amf_Server</title>
- <para>
- <classname>Zend_Amf_Server</classname> proporciona un servidor al estilo
- <acronym>RPC</acronym> para tramitar solicitudes hechas desde Adobe Flash Player
- utilizando el protocolo <acronym>AMF</acronym>. Al igual que todas las clases de servidor,
- Zend Framework sigue la <acronym>API</acronym> de SoapServer, proporcionando una interfaz
- para crear servidores fácil de recordar. </para>
- <example id="zend.amf.server.basic">
- <title>Servidor AMF básico</title>
- <para> Asumamos que ha creado la clase <classname>Foo</classname> con una variedad de
- métodos públicos. Usando el siguiente código, puede crear un servidor
- <acronym>AMF</acronym>: </para>
- <programlisting language="php"><![CDATA[
- $servidor = new Zend_Amf_Server();
- $servidor->setClass('Foo');
- $respuesta = $servidor->handle();
- echo $respuesta;
- ]]></programlisting>
- <para> Alternativamente, en su lugar puede elegir agregar una función simple como llamada de
- retorno: </para>
- <programlisting language="php"><![CDATA[
- $servidor = new Zend_Amf_Server();
- $servidor->addFunction('myUberCoolFunction');
- $respuesta = $servidor->handle();
- echo $respuesta;
- ]]></programlisting>
- <para> También puede combinar y examinar la identidad de varias clases y funciones. Al
- hacerlo, sugerimos darle un espacio de nombres a cada una para garantizar que no ocurran
- colisiones entre nombres de métodos; puede hacerse simplemente pasando una segunda
- cadena de argumentos para cualquier <methodname>addFunction()</methodname> o
- <methodname>setClass()</methodname>: </para>
- <programlisting language="php"><![CDATA[
- $servidor = new Zend_Amf_Server();
- $servidor->addFunction('myUberCoolFunction', 'my')
- ->setClass('Foo', 'foo')
- ->setClass('Bar', 'bar');
- $respuesta = $servidor->handle();
- echo $respuesta;
- ]]></programlisting>
- <para> El <classname>Zend_Amf_Server</classname> también permite cargar servicios
- dinámicamente, en función de una ruta de directorio ya suministrada. Puede añadir al
- servidor tantos directorios como desee. El orden en que se añadan los directorios al
- servidor será el orden en que se realizarán las búsquedas <acronym>LIFO</acronym> en los
- directorios para coincidir con la clase. El método
- <methodname>addDirectory()</methodname> realiza la acción de añadir directorios. </para>
- <programlisting language="php"><![CDATA[
- $servidor->addDirectory(dirname(__FILE__) .'/../services/');
- $servidor->addDirectory(dirname(__FILE__) .'/../package/');
- ]]></programlisting>
- <para> Cuando se llama a servicios remotos, los nombres de los directorios que contengan las
- fuentes pueden tener los delimitadores guión bajo ("_") y el punto ("."). Cuando se
- utilize un guión bajo ("_") tanto en <acronym>PEAR</acronym> como en Zend Framework, se
- respetarán los nombres de clases de acuerdo a las convenciones de nomenclatura. Esto
- significa que si usted llama al servicio com_Foo_Bar el servidor
- buscará el archivo <filename>Bar.php</filename> en cada una de las rutas incluidas en
- <filename>com/Foo/Bar.php</filename>. Si se usa la notación punto para su servicio
- remoto como <filename>com.Foo.Bar</filename> cada ruta incluida deberá tener
- <filename>com/Foo/Bar.php</filename> agregado al final para autocargar
- <filename>Bar.php</filename>
- </para>
- <para> Todos las solicitudes <acronym>AMF</acronym> enviadas al script serán manejadas por
- el servidor, y este devolverá una respuesta <acronym>AMF</acronym>. </para>
- </example>
- <note>
- <title>Todos los métodos y las funciones agregadas requieren bloques de documentación
- (docblocks)</title>
- <para> Como todos los demás componentes del servidor en Zend Framework, debe documentar los
- métodos de su clase usando <acronym>PHP</acronym> docblocks. Como mínimo, necesita
- proporcionar anotaciones para cada argumento así como para el valor de retorno. Como
- ejemplos: </para>
- <programlisting language="php"><![CDATA[
- // Función que agregar:
- /**
- * @param string $nombre
- * @param string $saludo
- * @return string
- */
- function holaMundo($ombre, $saludo = 'Hola')
- {
- return $saludo . ', ' . $nombre;
- }
- ]]></programlisting>
- <programlisting language="php"><![CDATA[
- // Clase agregada
- class Mundo
- {
- /**
- * @param string $nombre
- * @param string $saludo
- * @return string
- */
- public function hola($nombre, $saludo = 'Hola')
- {
- return $saludo . ', ' . $nombre;
- }
- }
- ]]></programlisting>
- <para> Pueden usarse otras anotaciones, pero serán ignoradas. </para>
- </note>
- <sect2 id="zend.amf.server.flex">
- <title>Conectándose al Servidor desde Flex</title>
- <para> Conectarse a <classname>Zend_Amf_Server</classname> desde su proyecto Flex es
- bastante simple; solo necesita apuntar el final del <acronym>URI</acronym> a su script
- <classname>Zend_Amf_Server</classname>. </para>
- <para> Por ejemplo, digamos que ya ha creado su servidor y lo ha puesto en el fichero
- <filename>server.php</filename> en el directorio raíz (root) de su aplicación, por
- lo tanto la <acronym>URI</acronym> es
- <filename>http://example.com/server.php</filename>. En este caso, usted debería
- modificar su fichero <filename>service-config.xml</filename> poniendo este valor como
- atributo al punto final del canal uri. </para>
- <para> Si nunca ha creado un fichero <filename>service-config.xml</filename> puede hacerlo
- abriendo su proyecto en la ventana del navegador. Haga clic derecho sobre el nombre del
- proyecto y seleccione 'properties' (propiedades). En el cuadro de diálogo 'properties'
- del proyecto ir al menú ‘Flex Build Path' (Crear ruta Flex), luego en la pestaña
- ‘Library path’ (ruta de biblioteca) asegúrese de que el fichero
- '<filename>rpc.swc</filename>' sea añadido a su ruta de proyectos y pulse Ok
- (Aceptar) para cerrar la ventana. </para>
- <para> También necesitará indicarle al compilador que debe usar
- <filename>service-config.xml</filename> para encontrar el punto final de
- RemoteObject. Para hacerlo, abra de nuevo el panel de propiedades de su proyecto
- haciendo clic en el botón derecho sobre el proyecto en la carpeta del navegador y
- seleccione 'properties' (propiedades). Ahora seleccione ‘Flex Compiler' (Compilador
- Flex) y añada la cadena: <command>-services "services-config.xml"</command>. Presione
- 'Apply' (Aplicar) y luego en OK para volver a actualizar la opción. Lo que acaba de
- hacer es decirle al compilador Flex que busque en el fichero
- <filename>services-config.xml</filename> aquellas variables que se usarán en tiempo
- de ejecución por la clase RemotingObject. </para>
- <para> Ahora, para conectarnos a nuestros métodos remotos debemos indicarle a Flex qué
- fichero de configuración de servicios utilizar. Por esta razón creamos un nuevo fichero
- '<filename>services-config.xml</filename>' en la carpeta src del proyecto Flex. Con
- click derecho sobre el proyecto y seleccionando 'new'(nuevo) 'File' (fichero), se abrirá
- una nueva ventana. Seleccione la carpeta del proyecto y luego nombre el archivo
- '<filename>services-config.xml</filename>' y presione 'finish' (finalizar). </para>
- <para> Flex ha creado y abierto el nuevo fichero <filename>services-config.xml</filename>.
- Utilice el siguiente texto de ejemplo para su fichero
- <filename>services-config.xml</filename>. Asegúrese de actualizar su punto final
- para que concuerde con el servidor. Asegúrese también de guardar el fichero. </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> Hay dos puntos clave en el ejemplo. En primer lugar, pero último en el listado,
- creamos un canal <acronym>AMF</acronym>, y especificamos el punto final como la URL a
- nuestro <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> Advierta que a este canal le hemos dado un identificador, "zend-endpoint". El ejemplo
- crea un servicio cuyo destino hace referencia a este canal, asignándole también un ID,
- en este caso es "zend". </para>
- <para> Dentro de nuestros ficheros Flex <acronym>MXML</acronym>, necesitamos vincular un
- RemoteObject al servicio. En <acronym>MXML</acronym>, esto podría hacerse así: </para>
- <programlisting language="xml"><![CDATA[
- <mx:RemoteObject id="myservice"
- fault="faultHandler(event)"
- showBusyCursor="true"
- destination="zend">
- ]]></programlisting>
- <para> Aquí, hemos definido un nuevo objeto remoto identificado por "myservice" vinculado
- destino de servicio "zend" que hemos definido en el fichero
- <filename>services-config.xml</filename>. Entonces invocamos sus métodos en nuestro
- ActionScript simplemente llamando a "myservice.<method>". . A modo de
- ejemplo: </para>
- <programlisting language="ActionScript"><![CDATA[
- myservice.hello("Wade");
- ]]></programlisting>
- <para> Cuando se usan nombres-de-espacio, puede usarse
- "myservice.<namespace>.<method>": </para>
- <programlisting language="ActionScript"><![CDATA[
- myservice.world.hello("Wade");
- ]]></programlisting>
- <para> Para más información sobre como invocar a Flex RemoteObject visite el sitio de ayuda
- de Adobe Flex 3 en:<ulink
- url="http://livedocs.adobe.com/flex/3/html/help.html?content=data_access_4.html"/>.
- </para>
- </sect2>
- <sect2 id="zend.amf.server.errors">
- <title>Manejo de errores</title>
- <para> Por defecto, todas las excepciones producidas en sus clases o funciones adjuntas
- serán capturados y devueltas como mensajes de error de <acronym>AMF</acronym> (AMF
- ErrorMessages). Sin embargo, el contenido de estos objetos de mensajes de error variará
- dependiendo de si el servidor está o no en modo "producción" (el estado por defecto). </para>
- <para> Cuando se está en modo de producción, únicamente el código de excepción será
- devuelto. Si desactiva el modo de producción, algo que debe hacerse sólo para probar --
- serán devueltos más detalles de la excepción: el mensaje de excepción (error), línea y
- backtrace serán adjuntados. </para>
- <para> Para desactivar el modo de producción, haga lo siguiente: </para>
- <programlisting language="php"><![CDATA[
- $server->setProduction(false);
- ]]></programlisting>
- <para> Para habilitarlo nuevamente, pase el valor <constant>TRUE</constant> en su lugar. </para>
- <programlisting language="php"><![CDATA[
- $server->setProduction(true);
- ]]></programlisting>
- <note>
- <title>¡Deshabilite el modo de producción racionalmente!</title>
- <para> Sugerimos deshabilitar el modo de producción solo cuando se está en modo de
- desarrollo. Los mensajes de excepción y los backtraces puede contener información
- sensible del sistema, y no desea que se pueda acceder a ellas desde el exterior.
- Aunque <acronym>AMF</acronym> es un formato binario, ahora al ser abierta la
- especificación, cualquiera puede potencialmente deserializar los datos. </para>
- </note>
- <para> Un área en la que se debe tener especialmente mucho cuidado son los errores propios
- de <acronym>PHP</acronym>. Cuando la directiva <acronym>INI</acronym>
- <property>display_errors</property> está habilitada, los errores de
- <acronym>PHP</acronym> de cualquier nivel del reporte actual serán pasados
- directamente a la salida, y potencialmente se podrían hacer estragos con las respuestas
- de <acronym>AMF</acronym>. Para prevenir estos problemas, sugerimos deshabilitar la
- directiva <property>display_errors</property> cuando se está en modo de producción.
- </para>
- </sect2>
- <sect2 id="zend.amf.server.response">
- <title>Respuestas de AMF</title>
- <para> En ocasiones es posible que quiera manipular ligeramente el objeto respuesta, es
- bastante usual querer devolver algunas cebeceras de mensajes adicionales. Puede hacerlo
- mediante el método del servidor <methodname>handle()</methodname> que devuelve el objeto
- respuesta. </para>
- <example id="zend.amf.server.response.messageHeaderExample">
- <title>Agregar cabeceras de mensaje a la respuesta de AMF</title>
- <para> En este ejemplo, añadiremos la cabecera de mensaje (MessageHeader) "foo" con el
- valor 'bar' a la respuesta antes de devolverla. </para>
- <programlisting language="php"><![CDATA[
- $respuesta = $servidor->handle();
- $respuesta->addAmfHeader(new Zend_Amf_Value_MessageHeader('foo', true, 'bar'))
- echo $respuesta;
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.amf.server.typedobjects">
- <title>Objetos tipados</title>
- <para> Similarmente a <acronym>SOAP</acronym>, <acronym>AMF</acronym> permite pasar objetos
- entre cliente y servidor. Esto le da una gran flexibilidad y coherencia a ambos
- entornos. </para>
- <para>
- <methodname>Zend_Amf</methodname> ofrece tres métodos para mapear ActionScript y objetos
- PHP. </para>
- <itemizedlist>
- <listitem>
- <para> Primero, usted puede crear uniones explícitas a nivel del servidor,
- utilizando el método <methodname>setClassMap()</methodname>. El primer argumento
- es el nombre de la clase de ActionScript, el segundo es el nombre de la clase
- <acronym>PHP</acronym> que lo mapea: </para>
- <programlisting language="php"><![CDATA[
- // Mapea la clase ActionScript 'ContactVO' a la clase PHP 'Contact':
- $servidor->setClassMap('ContactVO', 'Contact');
- ]]></programlisting>
- </listitem>
- <listitem>
- <para> Segundo, en su clase <acronym>PHP</acronym> puede ajustar la propiedad como
- pública mediante <varname>$_explicitType</varname>, con el valor
- representativo de la clase ActionScript que mapear: </para>
- <programlisting language="php"><![CDATA[
- class Contact
- {
- public $_explicitType = 'ContactVO';
- }
- ]]></programlisting>
- </listitem>
- <listitem>
- <para> Tercero, en un sentido similar, puede definir como público el método
- <methodname>getASClassName()</methodname> dentro de su clase. Este método
- debe devolver la clase ActionScript apropiada: </para>
- <programlisting language="php"><![CDATA[
- class Contact
- {
- public function getASClassName()
- {
- return 'ContactVO';
- }
- }
- ]]></programlisting>
- </listitem>
- </itemizedlist>
- <para> Aunque hemos creado <emphasis>ContactVO</emphasis> en el servidor, ahora tenemos que
- hacer su clase correspondiente en <acronym>AS3</acronym> para que el servidor pueda
- mapear el objeto. </para>
- <para> Haga clic derecho sobre la carpeta src del proyecto Flex y seleccione New ->
- ActionScript File. Nombre el fichero como ContactVO y pulse 'finish' (finalizar) para
- verlo. Copie el siguiente código en el fichero para terminar de crear la clase. </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 ProductVO():void {
- }
- }
- }
- ]]></programlisting>
- <para> La clase es sintácticamente equivalente a la de <acronym>PHP</acronym> del mismo
- nombre. Los nombres de variables son exactamente los mismos y necesitan estar en el
- mismo contenedor para trabajar correctamente. Hay dos meta tags <acronym>AS3</acronym>
- únicos en esta clase. El primero es vinculable y dispara un evento cuando es
- actualizada. El segundo es el tag RemoteClass y define que esta clase puede tener
- mapeado un objeto remoto con un nombre de alias, en este caso
- <emphasis>ContactVO</emphasis> Es obligatorio que en esta etiqueta(tag), el valor
- que se estableció es la clase PHP sea estrictamente equivalente. </para>
- <programlisting language="as"><![CDATA[
- [Bindable]
- private var myContact:ContactVO;
- private function getContactHandler(event:ResultEvent):void {
- myContact = ContactVO(event.result);
- }
- ]]></programlisting>
- <para> El siguiente resultado del evento debido a la llamada de servicio, se incorporó
- instantáneamente a <emphasis>ContactVO</emphasis> de Flex. Cualquier cosa que esté
- ligada a myContact será actualizada con los datos retornados por
- <emphasis>ContactVO</emphasis>. </para>
- </sect2>
- <sect2 id="zend.amf.server.resources">
- <title>Recursos</title>
- <para>
- <classname>Zend_Amf</classname> provides tools for mapping resource types returned by
- service classes into data consumable by ActionScript. </para>
- <para> In order to handle specific resource type, the user needs to create a plugin class
- named after the resource name, with words capitalized and spaces removed (so, resource
- type "mysql result" becomes MysqlResult), with some prefix, e.g.
- <classname>My_MysqlResult</classname>. This class should implement one method,
- <methodname>parse()</methodname>, receiving one argument - the resource - and
- returning the value that should be sent to ActionScript. The class should be located in
- the file named after the last component of the name, e.g.
- <filename>MysqlResult.php</filename>. </para>
- <para> The directory containing the resource handling plugins should be registered with
- <classname>Zend_Amf</classname> type loader: </para>
- <programlisting language="php"><![CDATA[
- Zend_Amf_Parse_TypeLoader::addResourceDirectory(
- "My",
- "application/library/resources/My"
- ));
- ]]></programlisting>
- <para> For detailed discussion of loading plugins, please see the <link
- linkend="zend.loader.pluginloader">plugin loader</link> section. </para>
- <para> Default directory for <classname>Zend_Amf</classname> resources is registered
- automatically and currently contains handlers for "mysql result" and "stream" resources. </para>
- <programlisting language="php"><![CDATA[
- // Example class implementing handling resources of type mysql result
- class Zend_Amf_Parse_Resource_MysqlResult
- {
- /**
- * Parse resource into array
- *
- * @param resource $resource
- * @return array
- */
- public function parse($resource) {
- $result = array();
- while($row = mysql_fetch_assoc($resource)) {
- $result[] = $row;
- }
- return $result;
- }
- }
- ]]></programlisting>
- <para> Trying to return unknown resource type (i.e., one for which no handler plugin exists)
- will result in an exception. </para>
- </sect2>
- <sect2 id="zend.amf.server.flash">
- <title>Conectándose al Servidor desde Flash</title>
- <para> La conexión a <classname>Zend_Amf_Server</classname> desde su proyecto Flash es
- ligeramente distinta a la de Flex. Sin embargo una vez que la conexión con Flash
- funcione con <classname>Zend_Amf_Server</classname> lo hará igual modo que con Flex. El
- siguiente ejemplo también puede ser utilizado desde un fichero Flex
- <acronym>AS3</acronym>. Para nuestra conexión vamos a reutilizar la misma
- configuracion <classname>Zend_Amf_Server</classname> junto a la clase Mundo. </para>
- <para> Abra Flash CS y cree un nuevo fichero Flash (ActionScript 3). Nombre al documento
- como <filename>ZendExample.fla</filename> y guárdelo en una carpeta que utilizará para
- este ejemplo. Cree una nuevo fichero <acronym>AS3</acronym> en el mismo directorio y
- llámelo <filename>Main.as</filename>. Abra ambos ficheros con su editor. Ahora vamos a
- conectar las dos ficheros a través de la clase documento. Seleccione ZendExample y haga
- clic en el escenario. Desde el panel del escenario cambie la propiedad de la clase
- Document a Main. Esto vincula al fichero Main.as con la interfaz de usuario
- en<filename>ZendExample.fla</filename> Cuando ejecute el fichero ZendExample de
- Flash se ejecutará ahora la clase <filename>Main.as</filename> El paso siguiente será
- añadir ActionScript para hacer una lamada <acronym>AMF</acronym>. </para>
- <para> Ahora vamos a hacer una clase Main(principal) para que podamos enviar los datos al
- servidor y mostrar el resultado. Copie el código siguiente en su fichero
- <filename>Main.as</filename> y luego vamos a recorrer el código para describir cuál
- es el papel de cada elemento. </para>
- <programlisting language="as"><![CDATA[
- package {
- import flash.display.MovieClip;
- import flash.events.*;
- import flash.net.NetConnection;
- import flash.net.Responder;
- public class Main extends MovieClip {
- private var gateway:String = "http://example.com/server.php";
- private var connection:NetConnection;
- private var responder:Responder;
- public function Main() {
- responder = new Responder(onResult, onFault);
- connection = new NetConnection;
- connection.connect(gateway);
- }
- public function onComplete( e:Event ):void{
- var params = "Sent to Server";
- connection.call("World.hello", 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> Primero tenemos que importar dos bibliotecas de ActionScript que realizan la mayor
- parte del trabajo. La primera es NetConnection que actúa como un tubo bidireccional
- entre el cliente y el servidor. La segunda es un objeto Responder que maneja los valores
- de retorno desde el servidor, y que están relacionados con el éxito o el fracaso de la
- llamada. </para>
- <programlisting language="as"><![CDATA[
- import flash.net.NetConnection;
- import flash.net.Responder;
- ]]></programlisting>
- <para> En la clase necesitaremos tres variables para representar a NetConnection, Responder,
- y la URL del gateway a nuestra instalación <classname>Zend_Amf_Server</classname>. </para>
- <programlisting language="as"><![CDATA[
- private var gateway:String = "http://example.com/server.php";
- private var connection:NetConnection;
- private var responder:Responder;
- ]]></programlisting>
- <para> En el constructor Main creamos un Responder(respondedor) y una nueva conexión al
- punto final de <classname>Zend_Amf_Server</classname>. El respondedor define dos
- diferentes métodos para manejar la respuesta desde el servidor. Por simplicidad los
- hemos llamado onResult y onFault. </para>
- <programlisting language="as"><![CDATA[
- responder = new Responder(onResult, onFault);
- connection = new NetConnection;
- connection.connect(gateway);
- ]]></programlisting>
- <para> La función onComplete se ejecuta tan pronto como la construcción ha concluido,
- enviando los datos al servidor. Necesitamos añadir una línea más que hace una llamada a
- la función <classname>Zend_Amf_Server</classname> Mundo->hola. </para>
- <programlisting language="as"><![CDATA[
- connection.call("Mundo.hola", responder, params);
- ]]></programlisting>
- <para> Cuando creamos la variable responder hemos definido las funciones onResult y onFault
- para manejar la respuesta proveniente del servidor. Hemos añadido la función OnResult
- para el resultado exitoso desde el servidor. Cada vez que se ejecuta apropiadamente el
- manejo de conexión con el servidor, el manejador de eventos llama esta función. </para>
- <programlisting language="as"><![CDATA[
- private function onResult(result:Object):void {
- // Muestra los datos devueltos
- trace(String(result));
- }
- ]]></programlisting>
- <para> La función onFault, se llama si hubo una respuesta nula desde el servidor. Esto
- ocurre cuando hay un error en el servidor, la <acronym>URL</acronym> al servidor es
- inválida, el servicio remoto o método no existe o cualquier otra cuestión relacionada
- con la conexión. </para>
- <programlisting language="as"><![CDATA[
- private function onFault(fault:Object):void {
- trace(String(fault.description));
- }
- ]]></programlisting>
- <para> La inclusión de ActionScript para realizar la conexión remota ha finalizado. Al
- ejecutar el fichero ZendExample, se establece una conexión con Zend_Amf. En resumen, se
- han añadido las variables requeridas para abrir una conexión con el servidor remoto, se
- han definido qué métodos se deben utilizar cuando su aplicación recibe una respuesta
- desde el servidor, y finalmente se han mostrado los datos de salida devueltos a través
- de <methodname>trace()</methodname>. </para>
- </sect2>
- <sect2 id="zend.amf.server.auth">
- <title>Authentication</title>
- <para>
- <classname>Zend_Amf_Server</classname> allows you to specify authentication and
- authorization hooks to control access to the services. It is using the infrastructure
- provided by <link linkend="zend.auth">
- <classname>Zend_Auth</classname>
- </link> and <link linkend="zend.acl">
- <classname>Zend_Acl</classname>
- </link> components. </para>
- <para> In order to define authentication, the user provides authentication adapter extening
- <classname>Zend_Amf_Auth_Abstract</classname> abstract class. The adapter should
- implement the <methodname>authenticate()</methodname> method just like regular <link
- linkend="zend.auth.introduction.adapters">authentication adapter</link>. </para>
- <para> The adapter should use properties <emphasis>_username</emphasis> and
- <emphasis>_password</emphasis> from the parent
- <classname>Zend_Amf_Auth_Abstract</classname> class in order to authenticate. These
- values are set by the server using <methodname>setCredentials()</methodname> method
- before call to <methodname>authenticate()</methodname> if the credentials are received
- in the <acronym>AMF</acronym> request headers. </para>
- <para> The identity returned by the adapter should be an object containing property
- <property>role</property> for the <acronym>ACL</acronym> access control to work. </para>
- <para> If the authentication result is not successful, the request is not proceseed further
- and failure message is returned with the reasons for failure taken from the result. </para>
- <para> The adapter is connected to the server using <methodname>setAuth()</methodname>
- method: </para>
- <programlisting language="php"><![CDATA[
- $server->setAuth(new My_Amf_Auth());
- ]]></programlisting>
- <para> Access control is performed by using <classname>Zend_Acl</classname> object set by
- <methodname>setAcl()</methodname> method: </para>
- <programlisting language="php"><![CDATA[
- $acl = new Zend_Acl();
- createPermissions($acl); // create permission structure
- $server->setAcl($acl);
- ]]></programlisting>
- <para> If the <acronym>ACL</acronym> object is set, and the class being called defines
- <methodname>initAcl()</methodname> method, this method will be called with the
- <acronym>ACL</acronym> object as an argument. The class then can create additional
- <acronym>ACL</acronym> rules and return <constant>TRUE</constant>, or return
- <constant>FALSE</constant> if no access control is required for this class. </para>
- <para> After <acronym>ACL</acronym> have been set up, the server will check if access is
- allowed with role set by the authentication, resource being the class name (or
- <constant>NULL</constant> for function calls) and privilege being the function name.
- If no authentication was provided, then if the <emphasis>anonymous</emphasis> role was
- defined, it will be used, otherwise the access will be denied. </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("Access not allowed");
- }
- ]]></programlisting>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|