[GENERIC] Zend_Translate:
[zend.git] / documentation / manual / en / module_specs / Zend_Amf-Server.xml
blob3336bbbd65e03c7875d23909ec1f07b304b0d873
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.amf.server">
4     <title>Zend_Amf_Server</title>
6     <para>
7         <classname>Zend_Amf_Server</classname> provides an <acronym>RPC</acronym>-style server for
8         handling requests made from the Adobe Flash Player using the <acronym>AMF</acronym>
9         protocol. Like all Zend Framework server classes, it follows the SoapServer
10         <acronym>API</acronym>, providing an easy to remember interface for creating servers.
11     </para>
13     <example id="zend.amf.server.basic">
14         <title>Basic AMF Server</title>
16         <para>
17             Let's assume that you have created a class <classname>Foo</classname> with a
18             variety of public methods. You may create an <acronym>AMF</acronym> server using the
19             following code:
20         </para>
22         <programlisting language="php"><![CDATA[
23 $server = new Zend_Amf_Server();
24 $server->setClass('Foo');
25 $response = $server->handle();
26 echo $response;
27 ]]></programlisting>
29         <para>
30             Alternately, you may choose to attach a simple function as a
31             callback instead:
32         </para>
34         <programlisting language="php"><![CDATA[
35 $server = new Zend_Amf_Server();
36 $server->addFunction('myUberCoolFunction');
37 $response = $server->handle();
38 echo $response;
39 ]]></programlisting>
41         <para>
42             You could also mix and match multiple classes and functions. When
43             doing so, we suggest namespacing each to ensure that no method name
44             collisions occur; this can be done by simply passing a second string
45             argument to either <methodname>addFunction()</methodname> or
46             <methodname>setClass()</methodname>:
47         </para>
49         <programlisting language="php"><![CDATA[
50 $server = new Zend_Amf_Server();
51 $server->addFunction('myUberCoolFunction', 'my')
52        ->setClass('Foo', 'foo')
53        ->setClass('Bar', 'bar');
54 $response = $server->handle();
55 echo $response;
56 ]]></programlisting>
58         <para>
59             The <classname>Zend_Amf_Server</classname> also allows services to be dynamically
60             loaded based on a supplied directory path. You may add as many directories as you wish
61             to the server. The order that you add the directories to the server will be the
62             order that the <acronym>LIFO</acronym> search will be performed on the directories to
63             match the class. Adding directories is completed with the
64             <methodname>addDirectory()</methodname> method.
65         </para>
67         <programlisting language="php"><![CDATA[
68 $server->addDirectory(dirname(__FILE__) .'/../services/');
69 $server->addDirectory(dirname(__FILE__) .'/../package/');
70 ]]></programlisting>
72         <para>
73             When calling remote services your source name can have underscore ("_") and dot (".")
74             directory delimiters. When an underscore is used <acronym>PEAR</acronym> and Zend
75             Framework class naming conventions will be respected. This means that if you call the
76             service com_Foo_Bar the server will look for the file
77             <filename>Bar.php</filename> in the each of the included paths at
78             <filename>com/Foo/Bar.php</filename>. If the dot notation is used for your remote
79             service such as <filename>com.Foo.Bar</filename> each included path will have
80             <filename>com/Foo/Bar.php</filename> append to the end to autoload
81             <filename>Bar.php</filename>
82         </para>
84         <para>
85             All <acronym>AMF</acronym> requests sent to the script will then be handled by the
86             server, and an <acronym>AMF</acronym> response will be returned.
87         </para>
88     </example>
90     <note>
91         <title>All Attached Methods and Functions Need Docblocks</title>
93         <para>
94             Like all other server components in Zend Framework, you must document your class
95             methods using <acronym>PHP</acronym> docblocks. At the minimum, you
96             need to provide annotations for each required argument as well as
97             the return value. As examples:
98         </para>
100         <programlisting language="php"><![CDATA[
101 // Function to attach:
104  * @param  string $name
105  * @param  string $greeting
106  * @return string
107  */
108 function helloWorld($name, $greeting = 'Hello')
110     return $greeting . ', ' . $name;
112 ]]></programlisting>
114         <programlisting language="php"><![CDATA[
115 // Attached class
117 class World
119     /**
120      * @param  string $name
121      * @param  string $greeting
122      * @return string
123      */
124     public function hello($name, $greeting = 'Hello')
125     {
126         return $greeting . ', ' . $name;
127     }
129 ]]></programlisting>
131         <para>
132             Other annotations may be used, but will be ignored.
133         </para>
134     </note>
136     <sect2 id="zend.amf.server.flex">
137         <title>Connecting to the Server from Flex</title>
139         <para>
140             Connecting to your <classname>Zend_Amf_Server</classname> from your Flex
141             project is quite simple; you simply need to point your endpoint <acronym>URI</acronym>
142             to your <classname>Zend_Amf_Server</classname> script.
143         </para>
145         <para>
146             Say, for instance, you have created your server and placed it in the
147             <filename>server.php</filename> file in your application root, and thus the
148             <acronym>URI</acronym> is <filename>http://example.com/server.php</filename>. In this
149             case, you would modify your <filename>services-config.xml</filename> file to set the
150             channel endpoint uri attribute to this value.
151         </para>
153         <para>
154             If you have never created a <filename>service-config.xml</filename> file you can do so
155             by opening your project in your Navigator window. Right click on the project name and
156             select 'properties'. In the Project properties dialog go into 'Flex Build Path' menu,
157             'Library path' tab and be sure the '<filename>rpc.swc</filename>' file is added to your
158             projects path and Press Ok to close the window.
159         </para>
161         <para>
162             You will also need to tell the compiler to use the
163             <filename>service-config.xml</filename> to find the RemoteObject endpoint. To do this
164             open your project properties panel again by right clicking on the project folder from
165             your Navigator and selecting properties. From the properties popup select 'Flex
166             Compiler' and add the string: <command>-services "services-config.xml"</command>. Press
167             Apply then OK to return to update the option. What you have just done is told the Flex
168             compiler to look to the <filename>services-config.xml</filename> file for runtime
169             variables that will be used by the RemotingObject class.
170         </para>
172         <para>
173             We now need to tell Flex which services configuration file to use for connecting to
174             our remote methods. For this reason create a new
175             '<filename>services-config.xml</filename>' file into your Flex project src folder. To
176             do this right click on the project folder and select 'new' 'File' which will popup a
177             new window. Select the project folder and then name the file
178             '<filename>services-config.xml</filename>' and press finish.
179         </para>
181         <para>
182             Flex has created the new <filename>services-config.xml</filename> and has it open. Use
183             the following example text for your <filename>services-config.xml</filename> file. Make
184             sure that you update your endpoint to match that of your testing server. Make sure you
185             save the file.
186         </para>
188         <programlisting language="xml"><![CDATA[
189 <?xml version="1.0" encoding="UTF-8"?>
190 <services-config>
191     <services>
192         <service id="zend-service"
193             class="flex.messaging.services.RemotingService"
194             messageTypes="flex.messaging.messages.RemotingMessage">
195             <destination id="zend">
196                 <channels>
197                     <channel ref="zend-endpoint"/>
198                 </channels>
199                 <properties>
200                     <source>*</source>
201                 </properties>
202             </destination>
203         </service>
204     </services>
205     <channels>
206         <channel-definition id="zend-endpoint"
207             class="mx.messaging.channels.AMFChannel">
208             <endpoint uri="http://example.com/server.php"
209                 class="flex.messaging.endpoints.AMFEndpoint"/>
210         </channel-definition>
211     </channels>
212 </services-config>
213 ]]></programlisting>
215         <para>
216             There are two key points in the example. First, but last in the
217             listing, we create an <acronym>AMF</acronym> channel, and specify the endpoint as the
218             <acronym>URL</acronym> to our <classname>Zend_Amf_Server</classname>:
219         </para>
221         <programlisting language="xml"><![CDATA[
222 <channel-definition id="zend-endpoint"
223     <endpoint uri="http://example.com/server.php"
224         class="flex.messaging.endpoints.AMFEndpoint"/>
225 </channel-definition>
226 ]]></programlisting>
228         <para>
229             Notice that we've given this channel an identifier, "zend-endpoint".
230             The example create a service destination that refers to this channel,
231             assigning it an ID as well -- in this case "zend".
232         </para>
234         <para>
235             Within our Flex <acronym>MXML</acronym> files, we need to bind a RemoteObject to the
236             service. In <acronym>MXML</acronym>, this might be done as follows:
237         </para>
239         <programlisting language="xml"><![CDATA[
240 <mx:RemoteObject id="myservice"
241     fault="faultHandler(event)"
242     showBusyCursor="true"
243     destination="zend">
244 ]]></programlisting>
246         <para>
247             Here, we've defined a new remote object identified by "myservice"
248             bound to the service destination "zend" we defined in the
249             <filename>services-config.xml</filename> file. We then call methods on it
250             in our ActionScript by simply calling "myservice.&lt;method&gt;".
251             As an example:
252         </para>
254         <programlisting language="ActionScript"><![CDATA[
255 myservice.hello("Wade");
256 ]]></programlisting>
258         <para>
259             When namespacing, you would use
260             "myservice.&lt;namespace&gt;.&lt;method&gt;":
261         </para>
263         <programlisting language="ActionScript"><![CDATA[
264 myservice.world.hello("Wade");
265 ]]></programlisting>
267         <para>
268             For more information on Flex RemoteObject invocation, <ulink
269             url="http://livedocs.adobe.com/flex/3/html/help.html?content=data_access_4.html">
270             visit the Adobe Flex 3 Help site</ulink>.
271         </para>
272     </sect2>
274     <sect2 id="zend.amf.server.errors">
275         <title>Error Handling</title>
277         <para>
278             By default, all exceptions thrown in your attached classes or
279             functions will be caught and returned as <acronym>AMF</acronym> ErrorMessages. However,
280             the content of these ErrorMessage objects will vary based on whether
281             or not the server is in "production" mode (the default state).
282         </para>
284         <para>
285             When in production mode, only the exception code will be returned.
286             If you disable production mode -- something that should be done for
287             testing only -- most exception details will be returned: the
288             exception message, line, and backtrace will all be attached.
289         </para>
291         <para>
292             To disable production mode, do the following:
293         </para>
295         <programlisting language="php"><![CDATA[
296 $server->setProduction(false);
297 ]]></programlisting>
299         <para>
300             To re-enable it, pass a <constant>TRUE</constant> boolean value instead:
301         </para>
303         <programlisting language="php"><![CDATA[
304 $server->setProduction(true);
305 ]]></programlisting>
307         <note>
308             <title>Disable production mode sparingly!</title>
310             <para>
311                 We recommend disabling production mode only when in development.
312                 Exception messages and backtraces can contain sensitive system
313                 information that you may not wish for outside parties to access.
314                 Even though <acronym>AMF</acronym> is a binary format, the specification is now
315                 open, meaning anybody can potentially deserialize the payload.
316             </para>
317         </note>
319         <para>
320             One area to be especially careful with is <acronym>PHP</acronym> errors themselves.
321             When the <property>display_errors</property> <acronym>INI</acronym> directive is
322             enabled, any <acronym>PHP</acronym> errors for the current error reporting level are
323             rendered directly in the output -- potentially disrupting the <acronym>AMF</acronym>
324             response payload. We suggest turning off the <property>display_errors</property>
325             directive in production to prevent such problems
326         </para>
327     </sect2>
329     <sect2 id="zend.amf.server.response">
330         <title>AMF Responses</title>
332         <para>
333             Occasionally you may desire to manipulate the response object
334             slightly, typically to return extra message headers. The
335             <methodname>handle()</methodname> method of the server returns the response
336             object, allowing you to do so.
337         </para>
339         <example id="zend.amf.server.response.messageHeaderExample">
340             <title>Adding Message Headers to the AMF Response</title>
342             <para>
343                 In this example, we add a 'foo' MessageHeader with the value
344                 'bar' to the response prior to returning it.
345             </para>
347             <programlisting language="php"><![CDATA[
348 $response = $server->handle();
349 $response->addAmfHeader(new Zend_Amf_Value_MessageHeader('foo', true, 'bar'))
350 echo $response;
351 ]]></programlisting>
352         </example>
353     </sect2>
355     <sect2 id="zend.amf.server.typedobjects">
356         <title>Typed Objects</title>
358         <para>
359             Similar to <acronym>SOAP</acronym>, <acronym>AMF</acronym> allows passing objects
360             between the client and server. This allows a great amount of flexibility and
361             coherence between the two environments.
362         </para>
364         <para>
365             <classname>Zend_Amf</classname> provides three methods for mapping
366             ActionScript and <acronym>PHP</acronym> objects.
367         </para>
369         <itemizedlist>
370             <listitem>
371                 <para>
372                     First, you may create explicit bindings at the server level,
373                     using the <methodname>setClassMap()</methodname> method. The first
374                     argument is the ActionScript class name, the second the <acronym>PHP</acronym>
375                     class name it maps to:
376                 </para>
378                 <programlisting language="php"><![CDATA[
379 // Map the ActionScript class 'ContactVO' to the PHP class 'Contact':
380 $server->setClassMap('ContactVO', 'Contact');
381 ]]></programlisting>
382             </listitem>
384             <listitem>
385                 <para>
386                     Second, you can set the public property <varname>$_explicitType</varname>
387                     in your <acronym>PHP</acronym> class, with the
388                     value representing the ActionScript class to map to:
389                 </para>
391                 <programlisting language="php"><![CDATA[
392 class Contact
394     public $_explicitType = 'ContactVO';
396 ]]></programlisting>
397             </listitem>
399             <listitem>
400                 <para>
401                     Third, in a similar vein, you may define the public method
402                     <methodname>getASClassName()</methodname> in your <acronym>PHP</acronym> class;
403                     this method should return the appropriate ActionScript class:
404                 </para>
406                 <programlisting language="php"><![CDATA[
407 class Contact
409     public function getASClassName()
410     {
411         return 'ContactVO';
412     }
414 ]]></programlisting>
415             </listitem>
416         </itemizedlist>
418         <para>
419             Although we have created the ContactVO on the server we now need to make its
420             corresponding class in <acronym>AS3</acronym> for the server object to be mapped to.
421         </para>
423         <para>
424             Right click on the src folder of the Flex project and select New -> ActionScript
425             File. Name the file ContactVO and press finish to see the new file. Copy the
426             following code into the file to finish creating the class.
427         </para>
429         <programlisting language="as"><![CDATA[
430 package
432     [Bindable]
433     [RemoteClass(alias="ContactVO")]
434     public class ContactVO
435     {
436         public var id:int;
437         public var firstname:String;
438         public var lastname:String;
439         public var email:String;
440         public var mobile:String;
441         public function ProductVO():void {
442         }
443     }
445 ]]></programlisting>
447         <para>
448             The class is syntactically equivalent to the <acronym>PHP</acronym> of the same name.
449             The variable names are exactly the same and need to be in the same case
450             to work properly. There are two unique <acronym>AS3</acronym> meta tags in this class.
451             The first is bindable which makes fire a change event when it is updated.
452             The second tag is the RemoteClass tag which defines that this class can
453             have a remote object mapped with the alias name in this case
454             <emphasis>ContactVO</emphasis>. It is mandatory that this tag the value that was set
455             is the <acronym>PHP</acronym> class are strictly equivalent.
456         </para>
458         <programlisting language="as"><![CDATA[
459 [Bindable]
460 private var myContact:ContactVO;
462 private function getContactHandler(event:ResultEvent):void {
463     myContact = ContactVO(event.result);
465 ]]></programlisting>
467         <para>
468             The following result event from the service call is cast instantly onto the Flex
469             ContactVO. Anything that is bound to myContact will be updated with the returned
470             ContactVO data.
471         </para>
472     </sect2>
474     <sect2 id="zend.amf.server.resources">
475         <title>Resources</title>
477         <para>
478             <classname>Zend_Amf</classname> provides tools for mapping resource types
479             returned by service classes into data consumable by ActionScript.
480         </para>
482         <para>
483             In order to handle specific resource type, the user needs to create a plugin class named
484             after the resource name, with words capitalized and spaces removed (so, resource
485             type "mysql result" becomes MysqlResult), with some prefix, e.g.
486             <classname>My_MysqlResult</classname>. This class should implement one method,
487             <methodname>parse()</methodname>, receiving one argument - the resource - and returning
488             the value that should be sent to ActionScript. The class should be located in the file
489             named after the last component of the name, e.g. <filename>MysqlResult.php</filename>.
490         </para>
492         <para>
493             The directory containing the resource handling plugins should be registered with
494             <classname>Zend_Amf</classname> type loader:
495         </para>
497         <programlisting language="php"><![CDATA[
498 Zend_Amf_Parse_TypeLoader::addResourceDirectory(
499     "My",
500     "application/library/resources/My"
502 ]]></programlisting>
504         <para>
505             For detailed discussion of loading plugins, please see
506             the <link linkend="zend.loader.pluginloader">plugin loader</link> section.
507         </para>
509         <para>
510             Default directory for <classname>Zend_Amf</classname> resources is registered
511             automatically and currently contains handlers for "mysql result" and "stream"
512             resources.
513         </para>
515         <programlisting language="php"><![CDATA[
516 // Example class implementing handling resources of type mysql result
517 class Zend_Amf_Parse_Resource_MysqlResult
519     /**
520      * Parse resource into array
521      *
522      * @param resource $resource
523      * @return array
524      */
525     public function parse($resource) {
526         $result = array();
527         while($row = mysql_fetch_assoc($resource)) {
528             $result[] = $row;
529         }
530         return $result;
531     }
533 ]]></programlisting>
535         <para>
536             Trying to return unknown resource type (i.e., one for which no handler plugin exists)
537             will result in an exception.
538         </para>
539     </sect2>
541     <sect2 id="zend.amf.server.flash">
542         <title>Connecting to the Server from Flash</title>
544         <para>
545             Connecting to your <classname>Zend_Amf_Server</classname> from your Flash project is
546             slightly different than from Flex. However once the connection Flash functions with
547             <classname>Zend_Amf_Server</classname> the same way is flex. The following example can
548             also be used from a Flex <acronym>AS3</acronym> file. We will reuse the same
549             <classname>Zend_Amf_Server</classname> configuration along with the World class for our
550             connection.
551         </para>
553         <para>
554             Open Flash CS and create and new Flash File (ActionScript 3). Name the document
555             <filename>ZendExample.fla</filename> and save the document into a folder that you will
556             use for this example. Create a new <acronym>AS3</acronym> file in the same directory
557             and call the file <filename>Main.as</filename>. Have both files open in your editor. We
558             are now going to connect the two files via the document class. Select ZendExample and
559             click on the stage. From the stage properties panel change the Document class to Main.
560             This links the <filename>Main.as</filename> ActionScript file with the user interface
561             in <filename>ZendExample.fla</filename>. When you run the Flash file ZendExample the
562             <filename>Main.as</filename> class will now be run. Next we will add ActionScript to
563             make the <acronym>AMF</acronym> call.
564         </para>
566         <para>
567             We now are going to make a Main class so that we can send the data to the server and
568             display the result. Copy the following code into your <filename>Main.as</filename> file
569             and then we will walk through the code to describe what each element's role is.
570         </para>
572         <programlisting language="as"><![CDATA[
573 package {
574   import flash.display.MovieClip;
575   import flash.events.*;
576   import flash.net.NetConnection;
577   import flash.net.Responder;
579   public class Main extends MovieClip {
580     private var gateway:String = "http://example.com/server.php";
581     private var connection:NetConnection;
582     private var responder:Responder;
584     public function Main() {
585       responder = new Responder(onResult, onFault);
586       connection = new NetConnection;
587       connection.connect(gateway);
588     }
590     public function onComplete( e:Event ):void{
591       var params = "Sent to Server";
592       connection.call("World.hello", responder, params);
593     }
595     private function onResult(result:Object):void {
596       // Display the returned data
597       trace(String(result));
598     }
599     private function onFault(fault:Object):void {
600       trace(String(fault.description));
601     }
602   }
604 ]]></programlisting>
606         <para>
607             We first need to import two ActionScript libraries that perform the bulk of the work.
608             The first is NetConnection which acts like a by directional pipe between the client and
609             the server. The second is a Responder object which handles the return values from the
610             server related to the success or failure of the call.
611         </para>
613         <programlisting language="as"><![CDATA[
614 import flash.net.NetConnection;
615 import flash.net.Responder;
616 ]]></programlisting>
618         <para>
619             In the class we need three variables to represent the NetConnection, Responder, and
620             the gateway <acronym>URL</acronym> to our <classname>Zend_Amf_Server</classname>
621             installation.
622         </para>
624         <programlisting language="as"><![CDATA[
625 private var gateway:String = "http://example.com/server.php";
626 private var connection:NetConnection;
627 private var responder:Responder;
628 ]]></programlisting>
630         <para>
631             In the Main constructor we create a responder and a new connection to the
632             <classname>Zend_Amf_Server</classname> endpoint. The responder defines two different
633             methods for handling the response from the server. For simplicity I have called these
634             onResult and onFault.
635         </para>
637         <programlisting language="as"><![CDATA[
638 responder = new Responder(onResult, onFault);
639 connection = new NetConnection;
640 connection.connect(gateway);
641 ]]></programlisting>
643         <para>
644             In the onComplete function which is run as soon as the construct has completed we send
645             the data to the server. We need to add one more line that makes a call to the
646             <classname>Zend_Amf_Server</classname> World->hello function.
647         </para>
649         <programlisting language="as"><![CDATA[
650 connection.call("World.hello", responder, params);
651 ]]></programlisting>
653         <para>
654             When we created the responder variable we defined an onResult and onFault function to
655             handle the response from the server. We added this function for the successful result
656             from the server. A successful event handler is run every time the connection is handled
657             properly to the server.
658         </para>
660         <programlisting language="as"><![CDATA[
661 private function onResult(result:Object):void {
662     // Display the returned data
663     trace(String(result));
665 ]]></programlisting>
667         <para>
668             The onFault function, is called if there was an invalid response from the server. This
669             happens when there is an error on the server, the <acronym>URL</acronym> to the server
670             is invalid, the remote service or method does not exist, and any other connection
671             related issues.
672         </para>
674         <programlisting language="as"><![CDATA[
675 private function onFault(fault:Object):void {
676     trace(String(fault.description));
678 ]]></programlisting>
680         <para>
681             Adding in the ActionScript to make the remoting connection is now complete. Running the
682             ZendExample file now makes a connection to <classname>Zend_Amf</classname>. In review
683             you have added the required variables to open a connection to the remote server, defined
684             what methods should be used when your application receives a response from the server,
685             and finally displayed the returned data to output via <methodname>trace()</methodname>.
686         </para>
687     </sect2>
689     <sect2 id="zend.amf.server.auth">
690         <title>Authentication</title>
692         <para>
693             <classname>Zend_Amf_Server</classname> allows you to specify authentication and
694             authorization hooks to control access to the services. It is using the infrastructure
695             provided by <link linkend="zend.auth"><classname>Zend_Auth</classname></link> and
696             <link linkend="zend.acl"><classname>Zend_Acl</classname></link> components.
697         </para>
699         <para>
700             In order to define authentication, the user provides authentication adapter extening
701             <classname>Zend_Amf_Auth_Abstract</classname> abstract class. The adapter should
702             implement the <methodname>authenticate()</methodname> method just like regular
703             <link linkend="zend.auth.introduction.adapters">authentication adapter</link>.
704         </para>
706         <para>
707             The adapter should use properties <emphasis>_username</emphasis> and
708             <emphasis>_password</emphasis> from the parent
709             <classname>Zend_Amf_Auth_Abstract</classname> class in order to authenticate. These
710             values are set by the server using <methodname>setCredentials()</methodname> method
711             before call to <methodname>authenticate()</methodname> if the credentials are received
712             in the <acronym>AMF</acronym> request headers.
713         </para>
715         <para>
716             The identity returned by the adapter should be an object containing property
717             <property>role</property> for the <acronym>ACL</acronym> access control to work.
718         </para>
720         <para>
721             If the authentication result is not successful, the request is not proceseed further
722             and failure message is returned with the reasons for failure taken from the result.
723         </para>
725         <para>
726             The adapter is connected to the server using <methodname>setAuth()</methodname> method:
727         </para>
729         <programlisting language="php"><![CDATA[
730 $server->setAuth(new My_Amf_Auth());
731 ]]></programlisting>
733         <para>
734             Access control is performed by using <classname>Zend_Acl</classname> object set by
735             <methodname>setAcl()</methodname> method:
736         </para>
738         <programlisting language="php"><![CDATA[
739 $acl = new Zend_Acl();
740 createPermissions($acl); // create permission structure
741 $server->setAcl($acl);
742 ]]></programlisting>
744         <para>
745             If the <acronym>ACL</acronym> object is set, and the class being called defines
746             <methodname>initAcl()</methodname> method, this method will be called with the
747             <acronym>ACL</acronym> object as an argument. The class then can create additional
748             <acronym>ACL</acronym> rules and return <constant>TRUE</constant>, or return
749             <constant>FALSE</constant> if no access control is required for this class.
750         </para>
752         <para>
753             After <acronym>ACL</acronym> have been set up, the server will check if access is
754             allowed with role set by the authentication, resource being the class name (or
755             <constant>NULL</constant> for
756             function calls) and privilege being the function name. If no authentication was
757             provided, then if the <emphasis>anonymous</emphasis> role was defined, it will be used,
758             otherwise the access will be denied.
759         </para>
761         <programlisting language="php"><![CDATA[
762 if($this->_acl->isAllowed($role, $class, $function)) {
763     return true;
764 } else {
765     require_once 'Zend/Amf/Server/Exception.php';
766     throw new Zend_Amf_Server_Exception("Access not allowed");
768 ]]></programlisting>
769     </sect2>
770 </sect1>
771 <!--
772 vim:se ts=4 sw=4 et: