| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074 |
- <?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
- <acronym>URI</acronym>
- .
- </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
- <acronym>URL</acronym>
- 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>
- (<acronym>AMF</acronym> 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>
- <classname>Zend_Amf</classname>
- ofrece tres métodos para mapear
- ActionScript y objetos
- <acronym>PHP</acronym>
- .
- </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
- <acronym>PHP</acronym>
- 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
- <acronym>URL</acronym>
- 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
- <classname>Zend_Amf</classname>
- . 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>
|