Avg. Rating 3.0
Tags:



Problem

I want to establish a communication between a Flex Application and a PHP application using the AMF protocol. The problem is that AMFPHP is somewhat outdated and poorly coded. Is there another solution I can use?

Solution

Of course, there is. Zend AMF is a new component in the Zend Framework which allows you to create a really neat Gateway in a few steps.

Detailed explanation

The Flex application


I have a simple application with a Button. When I click on that button, a request is sent to my webserver. This request is processed and sent back as a response to my Flex application. Finally, my application will show an alert box if the response is "valid".

package com.palleas.component
{
  import flash.events.MouseEvent;
 
  import mx.rpc.events.FaultEvent;
  import mx.rpc.events.ResultEvent;
  import mx.rpc.remoting.RemoteObject;
 
  import spark.components.Application;
  import spark.components.Button;
 
  public class Facade extends Application
  {
    protected var trigger:spark.components.Button;
   
    public function Facade()
    {
      super();
    }
   
    override protected function createChildren() : void
    {
      super.createChildren();
      trigger = new Button();
      trigger.label = "Click me, dude !";
      trigger.addEventListener(MouseEvent.CLICK, triggerClickHandler);
      addElement(trigger);
    }
   
    protected function triggerClickHandler(e:MouseEvent):void
    {

    // do something

    }
  }
}

On the PHP side:

<?php
set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).'/../');
require_once 'Zend/Amf/Server.php';

class Geek
{
  public $firstName;
  public $lastName;
  public $os;

}

class GeekService
{
  public function registerAsAUberGeek($firstName, $lastName, $os)
  {
    $geek = new Geek();
    $geek->firstName = $firstName;
    $geek->lastname = $lastName;
    $geek->os = $os;
    return $geek;
  }
}

$serverHandler = new Zend_Amf_Server();
$serverHandler->setClass('GeekService');
$serverHandler->setClassMap('com.palleas.vo.Geek','Geek');
echo $serverHandler->handle();

 

Let's explain it a bit :
set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).'/../');
require_once 'Zend/Amf/Server.php';

What I am saying here is that "this is where you have to look for the Zend Framework" and "Please load the Zend_Amf_Server" Class. I know it seems overly simple to explain it this way but 1.) it is fun for me and 2.) it makes it very easy to understand.

Class Geek {
// ...
}


This is my "PHP value object". I put it in my gateway file but of course it is much cleaner to put it in a "value-object", in the same package structure than the Actionscript value Object I'll show you in the next part of this recipe:
Actionscript path : com.palleas.vo.Geek
PHP path : com/palleas/vo/Geek.php
This way, it's easier for you to find something.

class GeekService {
// ...
}


This is where all the methods of my geek service will be written. Every request from my Flex application will call on these methods.

$serverHandler = new Zend_Amf_Server();
$serverHandler->setClass('GeekService');
$serverHandler->setClassMap('com.palleas.vo.Geek','Geek');
echo $serverHandler->handle();


There, i'm creating the objet which will handle the AMF request. This line :

$serverHandler->setClassMap('com.palleas.vo.Geek','Geek');
 

The above is probably the most important piece as it makes the "class mapping" work. Remember, class mapping is a way for Flex (Flash actually) and PHP to communicate throught objects. The first parameter is the "real name" of the class, the second is the name of the binded PHP class.


Back on the ActionScript side

 

First, we create the same "Geek" value-object as an Actionscript class :
package com.palleas.vo
{
  [RemoteClass(alias="com.palleas.vo.Geek")]
    public class Geek
    {
      public var firstName:String;
      public var lastName:String;
      public var os:String;
    }
}


You have probably noticed the new "RemoteClass" metatag. Just as the "setClassMap" did on the PHP side, this is how Flex specifies the "real name" of the Class.
 


The remote manager
 

Now it's time to make our Flex application fall in love with PHP, thanks to the awesone AMF protocol. To do that, let's use a RemoteObject, and a few parameters:

// ...
remotingManager = new RemoteObject("GeekService");
remotingManager.source = "GeekService";
remotingManager.endpoint = "http://labo.palleas.com/PHP/demoAMF/gateway.php";
remotingManager.addEventListener(FaultEvent.FAULT, faultServiceHandler);
remotingManager.addEventListener(ResultEvent.RESULT, resultServiceHandler);
// ...


(The first "GeekService" parameter is only specified to identify my service, which is useful when you configure all your services in a separate XML file)
The source and the endpoint parameters are the most important. The "source" parameter specifies which service we are going to use (here, it's "GeekService") and the "endpoint" is the URL to my gateway.

Last, but not least, we have two listeners handling the response of the remoting manager.

protected function faultServiceHandler(e:FaultEvent):void
{
  Alert.show("Woops, an error occured !");
}
   
protected function resultServiceHandler(e:ResultEvent):void
{
  if(!(e.result is Geek))
  {
    return; 
  }
 
  var newGeek:Geek = Geek(e.result);
  var message:String = "Yay!";
  message += newGeek.lastname + " " + newGeek.firstname;
  message += " is now registered as a UberGeek !";
  Alert.show(message);
}


I'm now calling the "registerAsAGeek" operation, when the user clicks on the button:

protected function triggerClickHandler(e:MouseEvent):void
{
  remotingManager.registerAsAUberGeek("Uber", "Geek", "Mac OS X");
}


And that's it for this simple use of Zend_AMF!

Report abuse

Related recipes