Integrate Flex Builder 3.0 & Php easly with the fresh ZendAMF


In this article I will explain how to build a simple adobe flex application that communicates with php using remote objects calls to the new AMF php implementation supported by adobe and called ZendAMF.

In my example I will use Adobe Flex Builder 3, ZendAMF and a Apache web server with php support and mysql server on windows. If you do not have any available server with php (at least) you will need to install one on your machine. It’s easy, nowadays you have many standalone installers that do everything, just look at the wampserver for example.

Requirements

Download Source Files

About ZendAMF:

ZendAMF is a new php implementation of Action Message Format (AMF) that allows Adobe Flex and Flash to talk with php. We could use the amfPHP, but because zend it’s a new one, I will use it. You can download it for free. The version that I will use is the ZendAMF 1.7.8 (zip).

About AMF:

AMF is a binary protocol that uses remote procedure calls to connect adobe flash & flex to many languages server-side and databases.

Getting started!

Some initial notes:

From now on I assume you got the wampserver installed on default path (c:wamp), Adobe Flex Builder 3 and have downloaded the ZendAMF 1.7.8 package (Zip File). To work with ZendAMF you don’t need to use the entire Zend Fframework.

1 – Creating the flex Project:

Just open Flex Builder, goto the menu File, select New and then Flex Project, on the screen it will ask you some informations, just write like me:

Project Name: phpintegration

Project Location: Select Default Project Location

Application type: Select Web Application (Runs in Flash Player)

Server Technology: None
New Flex Project
Click Next, and on the following screen leave the default values:

Output folder: bin-debug

Click next, and again on the screen leave all by default, that sould be:
Main source folder: src

Main application file: phpintegration.mxml

Output folder URL: (leave blank)
Click finish, your project is now created. It has nothing special, is just another regular flex project.

2 – Configuring ZendAMF

The next thing to do is to go to your web server htdocs path, if you have installed wampserver on default location should be c:wampwww, and extract here the downloaded zendAMF zip file.

It should now appear a folder on c:wampwww called ZendAMF-1.7.8 open it, then open library folder and copy the Zend folder, go back to the server root (c:wampwww) and paste the Zend folder.

This is all we need, you can leave the extracted ZendAMF-1.7.8 folder, it contains amf documentation, but Zend folder is all we need.

2.1 – Creating ZendAMF php files

In this path (c:wampwww), just create 2 files, one called zend_gateway.php and another called test_class.php

The two files have different functions and code:

zend-gateway.php is our gateway to flex, it means that flex will use this file to «find» all amf classes and our class test_class code.

Just put this code into this zend_gateway.php file:

<?php
 error_reporting(E_ALL | E_STRICT); //optional
 require_once "Zend/Amf/Server.php"; //the zendAMF server
 require_once "test_class.php";  //our test class
 $server = new Zend_Amf_Server(); //declare the server
 $server->setClass("test_class"); //load our test-class
 echo($server->handle()); // needed to start the server
?>

In our test_class.php file we put our class and functions that will be called from flex using a remote object :

<?php
class test_class {
	public function __construct() {
	 //this function is needed, is the constructor of class!!
	}
	public function sayHello($user=NULL) {
	   if($user==NULL) return 'Hello anonymous user! This is php saying hello!';
       else return 'Hello '.$user.'! This is php saying hello!';
    	}
}
?>

3 – Configuring the Flex Builder

When our php code is done, we just need to inform adobe flex compiler that he should identify this gateway (zend_gateway.php) and allow remote calls to it, for that we need to create a services-config.xml file and load it together with the compiler.

To easily do this, on the Adobe flex builder ‘Flex Navigator’ find the src folder and right-click on it, select New, then File and then just write on file name: services-config.xml and click finish. File will now open on flex builder (empty), just write this on it:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
    <services>
        <service id="amfphp-flashremoting-service" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="zend">
                <channels>
                    <channel ref="my-zend"/>
                </channels>
                <properties>
                    <source>*</source>
                </properties>
            </destination>
        </service>
    </services>
    <channels>
        <channel-definition id="my-zend" class="mx.messaging.channels.AMFChannel">
            <endpoint uri="http://localhost/zend_gateway.php" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>
</services-config>

In this code you will just need to modifiy (if necessary) the uri to your wamp server adress, by default this is correct and not need to be changed.

Save the file! (CTRL+S/ File->Save)

Now all we need to finish configuration is to inform the flex compiler that we have remote services by indicating the file services-config.xml as additional compiler arguments, to do this just go to your Adobe Flex Project, select (if not selected) the phpintegration.mxml file, go to flex builder menu: Project and select Properties, on the window opened, click at left on Flex Compiler, and on the right where is: -locale en_US just add: -services “services-config.xml”

It should now be (like the image):

-locale en_US -services “services-config.xml”
Compiler arguments

Click ok and wait a few seconds! Flex is configured!

4 – Coding our application

Our application is ready to code, we now need to add a few visual elements to our flex phpintegration.mxml file, in my case I will make a simple panel with a few items and 3 functions, one to call the php function, other to handle a success answer and a third to handle a possible error.

Just add the folowing code to the application:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
	<![CDATA[
		import mx.rpc.events.FaultEvent;
		import mx.rpc.events.ResultEvent;
		import mx.controls.Alert;

		private function onSayHelloResult(evt:ResultEvent):void {
			Alert.show(evt.result.toString(),"DONE!");
		}
		private function onError(err:FaultEvent):void {
			Alert.show(err.message.toString(),"ERROR!");
		}
		private function callZend():void {
			zendAMF.sayHello.arguments.user=userName.text;
			zendAMF.sayHello();
		}
	]]>
</mx:Script>
	<mx:Panel width="361" height="222" layout="absolute" title="Adobe Flex and PHP integration using ZendAMF" horizontalCenter="0" verticalCenter="0">
		<mx:Label x="26" y="53" text="Enter your name : "/>
		<mx:Label x="144" y="90" text="AND"/>
		<mx:TextInput x="144" y="51" id="userName"/>
		<mx:Button x="26" y="122" label="Call php sayHello() function!" width="278" click="callZend()"/>
	</mx:Panel>
	<mx:RemoteObject id="zendAMF" destination="zend" showBusyCursor="true" source="test_class">
	<mx:method name="sayHello" result="onSayHelloResult(event)"  fault="onError(event)">
			<mx:arguments>
				<user>
					{null}
				</user>
			</mx:arguments>
		</mx:method>
	</mx:RemoteObject>
</mx:Application>

It’s done!! Wou will get something like the image:
Final Project Layout
Just run the application and write your name on the text field (or leave blank) and press the button, if everything went good, you will get an alert with the one of the messages:

Hello anonymous user! This is php saying hello! If you did not write anything on the input field

or

Hello ‘name on the text field’ user! This is php saying hello! If you write something on the text field.

Let me explain the code step by step:

import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;

These are the needed imports to handle the events dispatched by the remote Object.

private function onSayHelloResult(evt:ResultEvent):void {
			Alert.show(evt.result.toString(),"DONE!");
		}

Called when the remoteObject receives an answer from the zendAMF (php return)

private function onError(err:FaultEvent):void {
			Alert.show(err.message.toString(),"ERROR!");
		}

Called when an error ocours, on the zendAMF server or the remoteObject.

private function callZend():void {
			zendAMF.sayHello.arguments.user=userName.text;
			zendAMF.sayHello();
		}

Function called by the button, on the fisrt line it defines the argument user with the text contained in the field userName. After that it calls the method from the remote object, that will call the same name function on the php class.

And finaly, the remote object:

<mx:RemoteObject id="zendAMF" destination="zend" showBusyCursor="true" source="test_class">
	<mx:method name="sayHello" result="onSayHelloResult(event)"  fault="onError(event)">
			<mx:arguments>
				<user>
					{null}
				</user>
			</mx:arguments>
		</mx:method>
	</mx:RemoteObject>

In here we define several things, on the remoteObject tag we define his id as zendAMF, indicating the zend destination (defined in the services-config.xml file loaded as compiler argument), we make it show the busyCursor during the call, and we define the destination class, that is our class name test_class.

On bottom, we define one method for each class function with the same name that our php function has, in this case we just need to call our sayHello function, defining it as is name: name=”sayHello”, we define also the function that will be called when the method responds, named onSayHelloResult, and also the function called when an error ocours, named onError. After that are named the arguments, should be placed by the same order that the php function have. In this caso is just one.

Well, that’s all.

Note

The zip archive FlexPHPSourceFiles.zip contains the flex project (phpintegration.zip) and the zendAMF path files (zendAMF.zip that containes zend_gateway.php and test_class.php)

In a future tutorial i will teach how to make a simple contact manager with all CRUD (Create, Read, Update and Delete) Operations using ZendAMF.


Did you enjoy this article?
Share the love
Get free updates and win TTL prizes

Other Posts You Might Like

15 Responses to “Integrate Flex Builder 3.0 & Php easly with the fresh ZendAMF”

  1. Wade Arnold says:

    Make sure in your bootstrap index.php file you set the handle to a variable and then echo the variable.

    echo($server->handle());

    should be:

    $handle = $server->handle();
    echo($handle)

    Great tutorial

  2. Emmanuel says:

    Hello Mario,

    Why do I get this particular error? I did add “services-config.xml” as argument in the flex compiler indeed, however, I am stack! I need help. Thanks.

    Severity and Description Path Resource Location Creation Time Id
    unable to open ‘C:\Program Files\Adobe\Flex Builder 3\sdks\3.0.0\frameworks\locale\en_US-services’ phpintegration Unknown 1246766484450 6

  3. Jonas says:

    Hi Mário,

    Mário if i don’t put this function

    private function callZend():void {
    zendAMF.sayHello.arguments.user=userName.text;
    zendAMF.sayHello();
    }
    The argument for the function sayHello always will be NULL?

    Well, Congrats for your tutorial is really good

  4. handoyo says:

    Hi,thanks for the tutor,but i can’t get it worked..I got this error message :

    [RPC Fault faultString="Send failed" faultCode="Client.Error.MessageSend" faultDetail="Channel.Connect.Failed error NetConnection.Call.BadVersion: : url: 'http://localhost/zend_gateway.php'"]
    at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::faultHandler()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\rpc\AbstractInvoker.as:220]
    at mx.rpc::Responder/fault()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\rpc\Responder.as:53]
    at mx.rpc::AsyncRequest/fault()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\rpc\AsyncRequest.as:103]
    at mx.messaging::ChannelSet/faultPendingSends()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\messaging\ChannelSet.as:1482]
    at mx.messaging::ChannelSet/channelFaultHandler()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\messaging\ChannelSet.as:975]
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at mx.messaging::Channel/connectFailed()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\messaging\Channel.as:997]
    at mx.messaging.channels::PollingChannel/connectFailed()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\messaging\channels\PollingChannel.as:354]
    at mx.messaging.channels::AMFChannel/statusHandler()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\messaging\channels\AMFChannel.as:390]

  5. AlejoQ says:

    Fantastic… Greetings from Ecuador…

  6. handoyo says:

    Sorry,i got it worked…Thanks a lot…

  7. Ced says:

    Bug with the last version: Zend AMF 1.8.4

  8. Jose D says:

    Hi, thanks for such a good tutorial. But I got the following error on clicking the button.

    (mx.messaging.messages::ErrorMessage)#0
    body = (Object)#1
    clientId = (null)
    correlationId = “406C7173-06D6-8155-A4E7-767E45053B12″
    destination = “”
    extendedData = (null)
    faultCode = “Client.Error.MessageSend”
    faultDetail = “Channel.Connect.Failed error NetConnection.Call.BadVersion: : url: ‘http://localhost/zend_gateway.php'”
    faultString = “Send failed”
    headers = (Object)#2
    messageId = “4F80D1E5-CC3C-55F1-7C58-767E45533F50″
    rootCause = (mx.messaging.events::ChannelFaultEvent)#3
    bubbles = false
    cancelable = false
    channel = (mx.messaging.channels::AMFChannel)#4
    authenticated = false
    channelSets = (Array)#5
    [0] (mx.messaging::ChannelSet)#6
    authenticated = false
    channelIds = (Array)#7
    [0] “my-zend”
    channels = (Array)#8
    [0] (mx.messaging.channels::AMFChannel)#4
    clustered = false
    connected = false
    currentChannel = (mx.messaging.channels::AMFChannel)#4
    initialDestinationId = (null)
    messageAgents = (Array)#9
    [0] (mx.rpc::AsyncRequest)#10
    authenticated = false
    autoConnect = true
    channelSet = (mx.messaging::ChannelSet)#6
    clientId = (null)
    connected = false
    defaultHeaders = (null)
    destination = “zend”
    id = “D4963F55-8BA8-C5FF-19E1-767A86C4CE11″
    reconnectAttempts = 0
    reconnectInterval = 0
    requestTimeout = -1
    subtopic = “”
    connected = false
    connectTimeout = -1
    enableSmallMessages = true
    endpoint = “http://localhost/zend_gateway.php”
    failoverURIs = (Array)#11
    id = “my-zend”
    mpiEnabled = false
    netConnection = (flash.net::NetConnection)#12
    client = (mx.messaging.channels::AMFChannel)#4
    connected = false
    objectEncoding = 3
    proxyType = “none”
    uri = “http://localhost/zend_gateway.php”
    piggybackingEnabled = false
    polling = false
    pollingEnabled = true
    pollingInterval = 3000
    protocol = “http”
    reconnecting = false
    recordMessageSizes = false
    recordMessageTimes = false
    requestTimeout = -1
    uri = “http://localhost/zend_gateway.php”
    url = “http://localhost/zend_gateway.php”
    useSmallMessages = false
    channelId = “my-zend”
    connected = false
    currentTarget = (mx.messaging.channels::AMFChannel)#4
    eventPhase = 2
    faultCode = “Channel.Connect.Failed”
    faultDetail = “NetConnection.Call.BadVersion: : url: ‘http://localhost/zend_gateway.php'”
    faultString = “error”
    reconnecting = false
    rejected = false
    rootCause = (Object)#13
    code = “NetConnection.Call.BadVersion”

  9. Vishal Jain says:

    How can we include multiple class file in zend_gateway.php

  10. reemul says:

    I got the same error as Jose D. I keep going over my code but can’t seem to pin it down.

    Jose D Says:
    October 21st, 2009 at 10:51 am

    Hi, thanks for such a good tutorial. But I got the following error on clicking the button.

    (mx.messaging.messages::ErrorMessage)#0
    body = (Object)#1
    clientId = (null)
    correlationId = “406C7173-06D6-8155-A4E7-767E45053B12″
    destination = “”
    extendedData = (null)
    faultCode = “Client.Error.MessageSend”
    faultDetail = “Channel.Connect.Failed error NetConnection.Call.BadVersion: : url: ‘http://localhost/zend_gateway.php’”
    faultString = “Send failed”
    headers = (Object)#2
    messageId = “4F80D1E5-CC3C-55F1-7C58-767E45533F50″
    rootCause = (mx.messaging.events::ChannelFaultEvent)#3
    bubbles = false
    cancelable = false
    channel = (mx.messaging.channels::AMFChannel)#4
    authenticated = false
    channelSets = (Array)#5
    [0] (mx.messaging::ChannelSet)#6
    authenticated = false
    channelIds = (Array)#7
    [0] “my-zend”
    channels = (Array)#8
    [0] (mx.messaging.channels::AMFChannel)#4
    clustered = false
    connected = false
    currentChannel = (mx.messaging.channels::AMFChannel)#4
    initialDestinationId = (null)
    messageAgents = (Array)#9
    [0] (mx.rpc::AsyncRequest)#10
    authenticated = false
    autoConnect = true
    channelSet = (mx.messaging::ChannelSet)#6
    clientId = (null)
    connected = false
    defaultHeaders = (null)
    destination = “zend”
    id = “D4963F55-8BA8-C5FF-19E1-767A86C4CE11″
    reconnectAttempts = 0
    reconnectInterval = 0
    requestTimeout = -1
    subtopic = “”
    connected = false
    connectTimeout = -1
    enableSmallMessages = true
    endpoint = “http://localhost/zend_gateway.php”
    failoverURIs = (Array)#11
    id = “my-zend”
    mpiEnabled = false
    netConnection = (flash.net::NetConnection)#12
    client = (mx.messaging.channels::AMFChannel)#4
    connected = false
    objectEncoding = 3
    proxyType = “none”
    uri = “http://localhost/zend_gateway.php”
    piggybackingEnabled = false
    polling = false
    pollingEnabled = true
    pollingInterval = 3000
    protocol = “http”
    reconnecting = false
    recordMessageSizes = false
    recordMessageTimes = false
    requestTimeout = -1
    uri = “http://localhost/zend_gateway.php”
    url = “http://localhost/zend_gateway.php”
    useSmallMessages = false
    channelId = “my-zend”
    connected = false
    currentTarget = (mx.messaging.channels::AMFChannel)#4
    eventPhase = 2
    faultCode = “Channel.Connect.Failed”
    faultDetail = “NetConnection.Call.BadVersion: : url: ‘http://localhost/zend_gateway.php’”
    faultString = “error”
    reconnecting = false
    rejected = false
    rootCause = (Object)#13
    code = “NetConnection.Call.BadVersion”

  11. Sasi says:

    Hi,

    Please help me to resolve this error.

    [RPC Fault faultString=”Send failed” faultCode=”Client.Error.MessageSend” faultDetail=”Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Status 406:

    Thanks in advance,
    Sasik.paul

  12. Oluwaseun says:

    Cool tutorial got me started on the ZendAMF Action Message Format ‘Broker’. I got into a hook though. When you enter the config file in the Flex Complier dialog, you should omit the quotes for the “services-config.xml” so you should have -services services-config.xml. Cool work. It worked like a bluebird (my term for really cool). I’m using the latest version zendamf 1.10.5 with flex sdk 3.5

  13. jhamer says:

    buenas noches

    mi nombre es jhamer soy de lima-peru , Apurimac-Abancay

    me podrian indicar donde puedo inscribirme para recibir clases via online para flex builder3 + mysql + php y trabajar con sus procedimientos almacenados de mysql y modificar datos de la estructurade php

    Jhamer Anderson Rojas Silva

  14. mansoor says:

    aweasme

  15. mansoor says:

    aweasme

Leave a Reply

TTL VIP
Become a TTL VIP Member & Get Notified of The Best Changes in Technology, Plus Win Prizes in Our VIP Only Contests...

Tech News Tech Tutorials Smartphone News Tablet News Gaming News Free Software Infographics Contact