Flash Remoting is great and I have used it for years, but there have always been a few things that have bothered me. Recently, I have discovered how to delivery AMF objects between the Flash Player and the server without having to establish a gateway or creating a Remoting connection. This article talks about how to deliver content with the benefits of Remoting over traditional HTTP requests.
Lately, I’ve been working on creating some commercial web services in PHP. One of the goals with the services was to permit a variety of clients to connect via different formats (XML, JSON, CSV, RSS, etc). We wanted to allow Flex applications to connect to the services and transfer data via ActionScript Message Format (AMF). AMF has a smaller footprint compared to other web formats because it is sent in a binary format. It also allows you serialize the data into native ActionScript classes between client and server. The standard means for delivering AMF is to use Flash Remoting. However, there I have found some common problems relating to developing with Flash Remoting:
Okay. Hopefully, you see my point. So, when Zend_Amf was released, we started exploring the possibilities of delivering content without Flash Remoting and it proved to be pretty simple.
What is Zend_Amf?
Zend_Amf is part of the Zend Framework for PHP (a collection of utility classes that addresses common tasks performed in PHP). Zend_Amf is sponsored by Adobe, developed by Wade Arnold. It is the Adobe’s officially supported PHP implementation for performing Flash Remoting via PHP. We are going to use this package to deliver our AMF content via HTTP. Flash Remoting already delivers content via HTTP, but it doesn’t expose the methods as clearly as what we are going to do.
You can download the Zend Framework from this site:
http://framework.zend.com
For more information regarding Zend_Amf you can access the documentation below. If you are not familiar with Flash Remoting, I would recommend reading this before proceeding.
http://framework.zend.com/manual/en/zend.amf.html
Delivering AMF from the Server using HTTP
We are going to first start out with a simple example for delivering our content. Here is the server code below:
Example 1.0 - amfout.php
// Include the Zend Loader include_once 'Zend/Loader.php'; // Tell the Zend Loader to autoload any classes we need // from the Zend Framework AMF package Zend_Loader::registerAutoload(); // Create a simple data structure $data = array('message' => 'Hello, world!'); // Create an instance of an AMF Output Stream $out = new Zend_Amf_Parse_OutputStream(); // We will serialize our content into AMF3 for this example // You could alternatively serialize it as AMF0 for legacy // Flash applications. $s = new Zend_Amf_Parse_Amf3_Serializer($out); $s->writeObject($data); // Return the content (we have found the newline is needed // in order to process the data correctly on the client side) echo "\n" . $out->getStream(); |
As you can see, to deliver AMF content from PHP is pretty straight forward. We create an instance of the output stream and then serialize our data into AMF. Returning the data from PHP is as simple as printing the stream. You will see that receiving the data in ActionScript is just as intuitive.
Example 1.1 - main.mxml - Flex Example of Parsing AMF
// Interior to mx:Application // call init() on applicationComplete private function init():void { // Create a UrlRequest var request:URLRequest = new URLRequest('http://[YOUR_URL]/amfout.php'); // Create a URLLoader using Binary Data Format var l:URLLoader = new URLLoader(request); l.dataFormat = URLLoaderDataFormat.BINARY; l.addEventListener(Event.COMPLETE, onComplete); } public function onComplete(event:Event):void { // Data comes in as ByteArray var ba:ByteArray = URLLoader(event.target).data as ByteArray; // Reading the data automatically serializes it to native // Flash Object var obj:Object = ba.readObject(); trace('Message:', obj.message); // Message: Hello, world! } |
Even though I have presented this example in Flex, it could have easily been ported to an ActionScript-Only project. You will note that we set the URLLoader to treat transferrable data as Binary. If we failed set this property, the data would be treated as a String and would have failed.
Delivering a Custom Data Class through HTTP
Let’s take our example one step further by creating a Value Object class that we can use to transfer data from the server to Flex using the meta-tag, RemoteClass.
Example 2.0 - contact.php - Declaring a Value Object in PHP
class Contact { public $first; public $last; public function getASClassName() { return get_class($this); // Contact } } |
Example 2.1 - amfout2.php - Using Contact Value Object
// Include the Zend Loader include_once 'Zend/Loader.php'; // Tell the Zend Loader to autoload any classes we need // from the Zend Framwork AMF package Zend_Loader::registerAutoload(); // Create a simple data structure $contact = new Contact(); $contact->first = 'John'; $contact->last = 'Smith'; // Create an instance of an AMF Output Stream $out = new Zend_Amf_Parse_OutputStream(); // We will serialize our content into AMF3 for this example // You could alternatively serialize it as AMF0 for legacy // Flash applications. $s = new Zend_Amf_Parse_Amf3_Serializer($out); $s->writeObject($contact); // Return the content (we have found the newline is needed // in order to process the data correctly on the client side) echo "\n" . $out->getStream(); |
Example 2.3 - Contact.as - ActionScript Value Object
package { [RemoteClass(alias="Contact")] [Bindable] public class Contact { public var first:String; public var last:String; public function get name():String { return first + " " + last; } } } |
Example 2.4 - main.mxml - Flex using ActionScript Value Object
// call init() on applicationComplete private function init():void { var request:URLRequest = new URLRequest('http://[YOUR_URL]/amfout2.php'); request.method = URLRequestMethod.POST; var l:URLLoader = new URLLoader(request); l.dataFormat = URLLoaderDataFormat.BINARY; l.addEventListener(Event.COMPLETE, onComplete); } public function onComplete(event:Event):void { var ba:ByteArray = URLLoader(event.target).data as ByteArray; var contact:Contact = ba.readObject(); trace('Contact:', contact.name); // Contact: John Smith } |
This example successfully sends data as a custom class from the server to Flex. The serialization converts it to the class by the usage of the meta-tag, RemoteClass.
Whether you have used AMF to deliver content through Flash Remoting or not, you will see that using this method is pretty simple. By using this technique, coding styles do not have to change, implementation is straight forward, and no additional APIs are needed in order to deliver the content.
In the next article, I will discuss how to transfer data from Flex to the server using this method.
[...] > rob [ON] code » Serializing Flash Objects over HTTP [...]
[...] Robert Taylor an OFG (Original Flash Gangster) and long term industry friend of mine wrote an interesting article on using the Zend Amf serialize to send back variables to Flash and Flex. I can honestly say that I would have NEVER though of using the serialize this way but it frankly is brilliant. What a super slick way to get typed data back into the Flash Player. Check out Serializing Flash Objects over HTTP [...]
This is really interesting! thanks!
Hey Rob,
these are pretty cool news! Thanx for sharing this!
Jan Viehweger
… ones more:
This opens the door for having alternative amf output for CMS like Typo3, Joomla etc. …
Yeah!!!
This was really useful. Thanks.
That’s a cool technique! Do you have a pattern for passing ActionScript objects to the PHP service? Obviously you can pass parameters in the URL (including potentially an output type, so the same service could respond AMF, XML etc). I am thinking specifically of cases I have where the request contains a complex AS object. Is it as simple as setting the data property of the URLRequest with the AS object?
Thanks
@Mark - I am preparing another article to talk about how to pass data from AS to PHP using this same technique.
Thanks, I will love to see a flex serialization of child added to stage in runtime or components position instead of objects!
hey Rob, cool tutorial. Will you be doing the flex -> php one soon? I’m interested to see how you do this, in particular I’m interested in how you transfer and store Date objects to php, mysql.
Conor
Yeah, I will be available next week.
That’s most understandable article about Zend AMF + Flash with serialization. Great! Thanks.