How to use Flex 2 RemoteObjects and PHP with SabreAMF

Author: Renaun Erickson
Date: August 31, 2006
Example Code Source

Introduction

Flex 2 provides many new and exciting features. One of the improvements is the new Action Message Format or AMF3. AMF is used with RemoteObject’s components and requires a compatible server. The newer AMF functionality provides improved performance and better object typing.

Current AMF integration is predominantly done through the ColdFusion connectivity update found in ColdFusion MX 7.0.2 and Flex Data Services. PHP and other open AMF projects have been catching up to the AMF field. More and more PHP servers and clients are supporting the AMF3 format, now it’s a question about how easy is it to integrate and use with Flex 2 applications. This article we’ll explore such a setup using SabreAMF.

This article assumes you understand how to install and configure PHP5 on a web server. If you need a quick way to install a PHP5 environment on windows I recommend XAMPP packages. You’ll find the code that is describe in this article by clicking on the “Example Code Source” link under the title.

SabreAMF

The SabreAMF project can be found on the OSFlash.org site. It supports AMF0 and AMF3. SabreAMF has been written for PHP5 only. The main developer behind this project is a guy by the name of Evert Pot. The SabreAMF package is licensed under a BDS license found here.

As of this article the latest package is SabreAMF-0.2.1906.tgz. For installing, if you have PEAR installed just call

pear install http://www.rooftopsolutions.nl/code/SabreAMF/downloads/SabreAMF-0.2.1906.tgz

Note: For more detailed installation instructions go to http://osflash.org/sabreamf and navigate to the “Installation instructions” section.

The Gateway and Service calls

One thing that is different as of yet with SabreAMF and other AMF servers is that the gateway is really up to you how to implement it. The current example is located at here. It shows how to setup a gateway class that catch all services and method calls and returns “hello world” regardless.

In this article we’ll proceed to create a basic gateway mechanism to call multiple classes and methods and return different types of values.

Make sure SabreAMF has been installed through PEAR. In this example I wish to point out that the folders and file names that we’ll be creating can be called whatever you would like. Continue by creating a folder “sabreamf” folder on the root of your web server that is running PHP5. Now create a gateway.php file and copy the code form the sample callbackserver.php (or see the code below)

[php] /* $Id: server.php 1218 2006-03-07 23:07:44Z evert $ */
// Include the server class
include ‘SabreAMF/CallbackServer.php’;

function myCallBack($service,$method,$data) {
return ‘hello world’;
}

// Init server
$server = new SabreAMF_CallbackServer();
$server->onInvokeService = ‘myCallBack’;
$server->exec();
?>[/php]This will be our endpoint for our Flex 2 RemoteObject class. Create a new Flex Project and create a SabreAMFExample.mxml file with the code below:

<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2006 Renaun Erickson (http://renaun.com)
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
creationComplete="doLogin()">

<mx:RemoteObject
id="roTestService"
destination="MyRemoteObjectDest"
endpoint="http://localhost/sabreamf/gateway.php"

result="Alert.show( event.result + ‘’, ‘Result’ )"
fault="Alert.show( event.fault.faultString , ‘Error’ )">
<mx:method name="HelloWorld" />
</mx:RemoteObject>

<mx:Script>
<![CDATA[
import mx.controls.Alert;

private function doLogin():void
{
roTestService.testMethod( "test", "test" );

}
]]>
</mx:Script>

<mx:Button label="Create Fault" click="roTestService.noMethod()" />

</mx:Application>

Go ahead and run the code and you’ll see that no matter what you call (ie: testMethod or noMethod) you get the same result. Now it is up to us to create the gateway and handle our services, methods, data and the faults.

Flex 2 and the services-config.xml

To take a quick side track let us talk about the services-config.xml file. The services-config.xml is a standard way of configuring Remoting Service, Proxy Service, Message Service, and Data Management Service. You’ll more information in the Adobe livedoc’s here. The name doesn’t have to be services-config.xml but to conform we’ll call ours just that. A side not is that in Flex Builder 2, when creating a New Project you get a “Create a Flex project” wizard with 3 options. These options are “Basic (e.g. XML or web service from PHP/JSP/ASP.NET)”, “ColdFusion Flash Remoting Service”, and “Flex Data Services”. The “ColdFusion Flash Remoting Service” project option is the closest to what we are doing. This project option defaults some compile options as well as some other project settings to use the default ColdFusion connectivity services-config.xml files and standalone ColdFusion webroot. We’ll be doing something similar by adding the compile argument into our Flex Project and pointed it to our own SabreAMF services-config.xml.

Go ahead now and create a services-config.xml file in the Flex Project root and put the following code inside:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="sabreamf-flashremoting-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">

<destination id="SabreAMF">
<channels>
<channel ref="my-sabreamf"/>
</channels>
<properties>
<source>*</source>
<access>
<use-mappings>false</use-mappings>
<!-- allow "public and remote" or just "remote" methods to be invoked -->
<method-access-level>remote</method-access-level>
</access>
</properties>
</destination>

</service>
</services>

<channels>
<channel-definition id="my-sabreamf" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://{server.name}:{server.port}{context.root}/sabreamf/gateway.php" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>false</polling-enabled>
<serialization>
<instantiate-types>false</instantiate-types>
</serialization>
</properties>
</channel-definition>
</channels>

<system>
</system>

</services-config>

The main parts to point out are first the services tag. This defines your services destination and channel name as well as valid source files. You’ll see we have defined the destination as “SabreAMF” and the channel as “my-sabreamf”. Now the sources tag as an * in it to mean all source files for the services are valid. The channel is used in the channels section where our endpoint is now defined. This way it is very easy to compile your application against another endpoint gateway without going in your code and changing all your RemoteObject components. The destination will be the piece that we define in the RemoteObject components and what will link it all together.

Go ahead and update the SabreAMFExample.mxml file to look like the code below:

<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2006 Renaun Erickson (http://renaun.com)
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
creationComplete="doLogin()">

<mx:RemoteObject
id="roTestService"
destination="SabreAMF"
source="MyTestService"

result="Alert.show( event.result + ‘’, ‘Result’ )"
fault="Alert.show( event.fault.faultString , ‘Error’ )">
<mx:method name="HelloWorld" />
</mx:RemoteObject>

<mx:Script>
<![CDATA[
import mx.controls.Alert;

private function doLogin():void
{
roTestService.testMethod( "test", "test" );

}
]]>
</mx:Script>
<mx:Button label="Create Fault" click="roTestService.noMethod()" />

</mx:Application>

We have dropped the endpoint attribute and included a source property now, and the destination now reflects what we defined in our services-config.xml. You’ll need to click on Project -> Properties -> Flex Compiler and add “-services services-config.xml” to the “Additional compiler arguments:” text box. Now you can run it and see that we still get “hello world” regardless of which source or method we call.

My Custom Extending of SabreAMF

For SabreAMF to do what I am used to with AMFPHP and ColdFusion I had to extend the package quite a bit. The extended package checks the validity of Classes and Method as expected. My modified SabreAMF classes can be downloaded here.

Now the gateway.php looks like:

[php] /*
Author 2006 Renaun Erickson (http://renaun.com)
*/

// Include the server class
include ‘SabreAMF/CallbackServer.php’;

// Init server
$server = new SabreAMF_CallbackServer();
$server->setBaseClassPath( “services/” );
$server->exec();
?>
[/php]

Just copy my modified SabreAMF files found in the SabreAMF-0.2.1906-extended.zip zip file over your php/PEAR/SabreAMF install directory. Then download the SabreAMFExampleSource.zip file. Unzip the file and then put the files under the php folder in your PHP webroot. The files under the flex folder go into your Flex Project.

This article got a little off track at the end but that is because its probably still incomplete. Once code and examples settle down some more I’ll revamp this article to reflect the next wave of changes.

Summary

SabreAMF provides Flex 2 access to an AMF0 and AMF3 PHP server. It is setup to very basic and does not do a lot of behind the scene lifting for you. Still this article shows how to SabreAMF hooked up and working the Flex 2. And hopefully we’ll see many more AMF3 PHP server implementations in the future, (WebORB for PHP and some day an AMF3 compatible AMFPHP).

All my source Flex 2 and PHP classes are located here