Adobe AIR 1.5.1 is out
The AIR 1.5.1 runtime was released today. While it’s a minor release, it includes a number of bug fixes. The runtime is available for Win, Mac OS, and Linux. You can download it from here.
You can read more about this on the Adobe AIR Team blog.
Do you want to fix some Flex SDK bugs?
On March 28th there will be a gathering of Flex connaisseurs to fix Flex SDK bugs. If you are interested in this, just go to this URL and sign in.
You can participate in person (if you live in Seattle area), or over the Internet.
Do you want to join the Flex Builder Pre-Release Program?
As you know, we are working hard on the next version of Flex Builder (code name Gumbo). There will be many additions that should appeal to PHP developers, and we want to hear your thoughts on these features. So, if you want to have the chance to be part of the Flex Builder pre-release program, just visit this link and fill in the survey: http://www.surveymonkey.com/s.aspx?sm=p1w3z8obcRi28iht1_2fFzbQ_3d_3d
Flex and ActionScript frameworks and libraries
A while ago, Piotr created a presentation about some of the available tools, frameworks, and libraries for Flex developers. I love it (to tell you the truth, I didn’t know there were so many), so I decided to add some additional info, and create a permanent page on my blog.
So here it comes the Flex Frameworks directory list!
Flash Camp and PHP UK Conference
This Thursday there will be a Flash Camp in London. Mike Chambers, Lee Brimelow, and Serge Jespers are speakers. I will attend the event, but I will save my breath for the PHP UK Conference, where I will do a session on Flex and AIR for PHP programmers. You can read more about the PHP conference over here, and about the Flash Camp here.
See you there, people!
FlexCamp Timisoara, Romania
| March 13, 2009 | to | March 15, 2009 |
The first Romanian FlexCamp outside of Bucharest!
Introduction in Flex – Craiova
| March 12, 2009 |
BootCamp in Craiova! Going with Miti.
The first Romanian FlexCamp outside of Bucharest
People, people! the time has come! On March 14th, we will have the first Romanian Flex Camp outside of Bucharest. After three editions at Adobe’s Bucharest office, we finally gave in to all of you who requested an event in another city. And the winner issssssss Timisoara! If you live in Timisoara or nearby, and on that very Saturday you are able to get up in the morning, and you didn’t forget to register here, then you should come.
This will probably be the best event so far, beacause we have interesting sessions, and we plan to end the day with a Boot Camp to give you enough fuel to get a quick start with Flex and Adobe AIR.
And hopefully, after the event ends, we will have enough energy to go out for beer!
Flex and PHP: remoting with WebORB
Whenever you want to do remoting, you need a server-side library that will handle that part of communication. For PHP backends you have a choice of four libraries: Zend AMF (the latest on this stage), AMFPHP, WebORB for PHP, and SabreAMF. I’ve already written articles on two of them, AMFPHP and ZendAMF. In this post I will focus on WebORB. Next, I will play with SabreAMF, and I will finish this series with an article comparing them.
You can download a Flex Builder project that contains the code for this article from here. Inside of the archive you will find a readme.txt file explaining what to do with it.
Installing WebORB for PHP
After downloading WebORB for PHP (you need to register first), just extract the files somewhere on your computer. Next create a folder called weborb inside of your PHP web server, and then copy the content of the archive you’ve just extracted into it. You should end up with a folder that have a bunch of folders and files (see the Figure 1).
Figure 1. Folder structure of WebORB for PHP.
WebORB comes with a lot of examples, and it also comes with a console that let’s you do a lot of things, including learning the basics of WebORB, seeing the available services exposed by WebORB, accessing the many Flex sample applications that came with WebORB (see Figure 2). You can find much more more information on this page.
Figure 2. WebORB console.
What is AMF and remoting and why should you use it?
If you already know these answers, you may want to skip to the next section. Let’s start by understanding remote procedure calls. Remote procedure calls let Flex applications make direct calls on the methods of your server side classes. Using BlazeDS or LiveCycle Data Services you can expose your Java and ColdFusion classes to the Flex application. However, if you use PHP you need a third party library on the server to expose PHP classes directly. Existing solutions include Zend AMF, WebORB, and AMFPHP. AMF is a binary protocol for serializing the messages. Because it is binary, it is more efficient in terms of bandwidth and server processing load than JSON or XML methods. If you want to see for yourself how much more efficient it is, James Ward has put together a nice benchmark.
WebORB is a PHP library that knows how to serialize and deserialize the AMF protocol, and thus lets you expose PHP classes to Flex applications. Another compelling reason for using remoting is code reuse. Because you can call methods on PHP classes and these methods can return PHP objects, you don’t have to modify your existing code to output JSON or XML.
As I noted earlier, WebORB remoting uses AMF to serialize messages between the server and Flex client. It also offers the ability to map an ActionScript class to a PHP class. For example, suppose you want to display in Flex the information from a table with the following structure:
1: contacts
2: -------------------------------
3: id primary key int
4: name varchar(255)
5: email varchar(255)
When using remoting, you create an ActionScript class to model this data in the client and a PHP class to model the same data on the server. When you create the PHP class that you want to call from Flex, you add a method that, for example, retrieves all the contacts from the table. This method will return an array of PHP VO classes, and in Flex you will get an array of ActionScript objects. All the conversions from PHP objects to AMF to ActionScript objects are done automatically for you by Flex and WebORB.
When you use XML or JSON for remoting, you’ll typically need extra steps in Flex to process the data in order to display or store it.
Let’s look at a working example.
Create the Flex PHP project
Usually, when I work with Flex and PHP projects, I prefer to use Flex Builder and Zend Studio installed together. It is possible, however, to work with Flex Builder and a PHP plugin to help you with the PHP code. Either way, you should create a Flex project that uses PHP on the server side (if you plan to use Zend Studio and Flex Builder, first create a Zend PHP Project, then use the Add Flex Nature wizard to add Flex PHP nature on the project). This way you streamline the deployment of the SWF file (the compiled result of the Flex project) to the PHP server. I chose to create a new project called “flex_weborb”.
Choose New > Folder, and then click on the Advanced button, and select the option Link to folder in the file system. Next, click the Browse button and chose the weborb folder you created earlier (the folder that holds the content of the WebORB archive).
Create the PHP code
All the PHP classes you want to expose to the Flex client need to be inside of the folder weborb/Services. If you navigate to this folder, you will find a bunch of files already in there. These are the services used by the samples that come with the framework. It is possible to separate the files in folders created inside of the Services folder. So you can have a class that is inside of a folder weborb/Services/org/corlan/utils/. Another thing, usually you use a VO to wrap one piece of information. This could be stored inside of the same weborb/Services folder. You don’t have to do anything special to configure the VO, you just place it under the weborb/Services folder, and use it inside of your PHP service class.
In the “weborb/Services” folder, create a PHP file called MyService.php, and in the folder weborb/Services/vo create a PHP file called VOAuthor.php. Open the MyService.php page and paste the following code (you need to update the connection information for your specific database setup; to do this, look for the four constants at the top of the class):
1: <?php
2: require_once ('vo/VOAuthor.php');
3:
4: //conection info
5: define( "DATABASE_SERVER", "localhost");
6: define( "DATABASE_USERNAME", "mihai");
7: define( "DATABASE_PASSWORD", "mihai");
8: define( "DATABASE_NAME", "flex360");
9:
10: class MyService {
11:
12: public function getData() {
13: //connect to the database.
14: $mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD);
15: mysql_select_db(DATABASE_NAME);
16: //retrieve all rows
17: $query = "SELECT id_aut, fname_aut, lname_aut FROM authors_aut ORDER BY fname_aut";
18: $result = mysql_query($query);
19:
20: $ret = array();
21: while ($obj = mysql_fetch_object($result, "VOAuthor")) {
22: $ret[] = $obj;
23: }
24: mysql_free_result($result);
25: return $ret;
26: }
27:
28: public function saveData($author) {
29: if ($author == NULL)
30: return NULL;
31: //logMe($author);
32: //connect to the database.
33: $mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD);
34: mysql_select_db(DATABASE_NAME);
35: //save changes
36: $query = "UPDATE authors_aut SET fname_aut='".$author->fname_aut."', lname_aut='".$author->lname_aut."' WHERE id_aut=". $author->id_aut;
37: $result = mysql_query($query);
38: return NULL;
39: }
40: }
41:
42: function logMe($var) {
43: $filename = dirname(__FILE__) . '/__log.txt';
44:
45: if (!$handle = fopen($filename, 'a')) {
46: echo "Cannot open file ($filename)";
47: return;
48: }
49:
50: $toSave = var_export($var, true);
51: fwrite($handle, "[" . date("y-m-d H:i:s") . "]");
52: fwrite($handle, "\n");
53: fwrite($handle, $toSave);
54: fwrite($handle, "\n");
55: }
56: ?>
This is the class you will call from Flex. It has two methods: one to get all the records from the table, and another to update the values for one record.
Let’s create the code for the Value Object, the data model. This is used by the MyService class to wrap one row from the table. Thus, the method getData() returns an array of VOAuthor, and the method saveData() receives one argument: the VOAuthor of the row that was changed. Open the file VOAuthor.php and add this code:
1: <?php
2: class VOAuthor {
3: public $id_aut;
4: public $fname_aut;
5: public $lname_aut;
6: }
7: ?>
As you can see, this class is very simple; it just provides the same members as the fields from the table.
Creating the Flex application
Now, that you have the PHP code in place, you are ready to create the Flex code that will call the PHP class. I want the Flex application to have a button that gets the data from the server, uses a data grid to display the data, and enables the user to edit any cell (with the exception of the id field) within the data grid. Whenever a cell is edited, the update is sent automatically to the server and saved to the database as well.
First, be sure to select the Flex perspective from the top right icons of Eclipse.
The next thing you need to do is to configure the destination on the server in order to make calls to PHP classes from Flex. WebORB comes with all these configuration files created. If you go to the weborb/Weborb/WEB-INF/flex folder, you will find these files: services-config.xml, remoting-config.xml, and messaging-config.xml. First, you need to open the services-config.xml file and locate the opening node <channels>, and add after this code (pay attention to the uri attribute of the endpoint node; in my case the URL to weborb.php is http://localhost/weborb/weborb.php, though on your machine it could be different):
1: <channel-definition id="my-amf-weborb" class="mx.messaging.channels.AMFChannel">
2: <endpoint uri="http://localhost/weborb/weborb.php" class="flex.messaging.endpoints.AMFEndpoint"/>
3: <properties>
4: <polling-enabled>false</polling-enabled>
5: </properties>
6: </channel-definition>
Save the file, and then open the remoting-config.xml file, and add a new destination:
1: <destination id="GenericFlexDestination">
2: <channels>
3: <channel ref="my-amf-weborb"/>
4: </channels>
5: <properties>
6: <source>*</source>
7: </properties>
8: </destination>
You use this destination from Flex to make calls to the PHP services stored in the weborb/Services folder. You need to configure the Flex application to use the services-config.xml configuration file. To do that, open the properties panel for the project (right click the project name, and choose Properties), click on Flex compiler, and add a new command –services and the absolute path to services-config.xml file (see Figure 3).
Figure 3. Adding the -services compiler argument.
Click OK, and now you are ready to write the Flex code. Open the file flex_weborb.mxml if you haven’t already opened it, and paste this code:
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
3: <mx:Script>
4: <![CDATA[
5: import mx.controls.Alert;
6: import mx.rpc.events.FaultEvent;
7: import org.corlan.VOAuthor;
8: import mx.events.DataGridEvent;
9: import mx.rpc.events.ResultEvent;
10:
11: private var item:VOAuthor;
12:
13: private function init():void {
14: myRPC.getData();
15: }
16: private function getDataListener(event:ResultEvent):void {
17: dg.dataProvider = event.result;
18: }
19: private function editListener(eventataGridEvent):void {
20: item = event.itemRenderer.data as VOAuthor;
21: }
22: private function saveDataListener(event:ResultEvent):void {
23: item = null;
24: init();
25: }
26: private function saveData():void {
27: if (item == null)
28: return;
29: myRPC.saveData(item);
30: }
31: private function faultListener(event:FaultEvent):void {
32: Alert.show(event.fault.faultString);
33: }
34:
35: ]]>
36: </mx:Script>
37:
38: <mx:RemoteObject id="myRPC" destination="GenericFlexDestination" source="MyService" fault="faultListener(event)">
39: <mx:method name="getData" result="getDataListener(event)"/>
40: <mx:method name="saveData" result="saveDataListener(event)"/>
41: </mx:RemoteObject>
42: <mx:VBox>
43: <mx:DataGrid id="dg" editable="true" itemEditEnd="editListener(event)" />
44: <mx:Button label="Save" click="saveData()" />
45: <mx:Button label="Get Data" click="init()" />
46: </mx:VBox>
47: </mx:Application>
I use the mx:RemoteObject to make the calls to the MyService PHP class from the server:
1: <mx:RemoteObject id="myRPC" destination="GenericFlexDestination" source="MyService" fault="faultListener(event)">
2: <mx:method name="getData" result="getDataListener(event)"/>
3: <mx:method name="saveData" result="saveDataListener(event)"/>
4: </mx:RemoteObject>
The destination attribute has the same value as the id value of the destination defined in the remoting-config.xml file (thus I am telling Flex that this is the destination I want to use). The source attribute points to the PHP class for which I want to make the calls. If the PHP class would have been in a folder that is in the Services folder, than I would use the folder names before the PHP class name with dot notation. For example, if you have MyService in weborb/Services/org/corlan, then the value of the source attribute is org.corlan.MyService.
Next I have defined the two methods I want to call on the PHP class (getData() and saveData()), and I set the result listeners for each method (these are the functions that will be called once the Flex application receives the response from the server).
For the UI I am using a DataGrid to display the data and edit inline the two text fields (first name and last name). I have a button to trigger the saving of the data back to server. On the DataGrid I have another listener registered for the end editing event, and the function registered gets called whenever something is edited in the DataGrid.
As you remember, I use a PHP object (VOAuthor) to wrap each row from the table. And I said that with remoting it is possible to get the conversion automatically from the PHP type to the proper ActionScript type. To do this, all you need to do is to create the ActionScript object. So just create a new ActionScript class with the package org.corlan, and the name VOAuthor. Paste this code in the class:
1: package org.corlan {
2:
3: [RemoteClass(alias="vo.VOAuthor")]
4: [Bindable]
5: public class VOAuthor {
6:
7: public var id_aut:int;
8: public var fname_aut:String;
9: public var lname_aut:String;
10: }
11: }
As you can see this class has the same members as the PHP class. It is very important to set the correct value for the alias attribute from the RemoteClass metatag. This tag tells the Flex application to what the corresponding server-side class is for this ActionScript class. In this case, the value vo.VOAuthor means that in the weborb/Services, there is a vo folder, and inside of it there is a VOAuthor PHP class.
And with that you should be ready to run the project and edit the data. To edit the data, just double click inside of a cell (see Figure 4).
Figure 4. The application with sample data.
Conclusion
WebORB handles the remoting as well as all the other frameworks. So there is nothing spectacular here. However, WebORB for PHP offers more than remoting. First of all, it offers data messaging (Publisher/Subscriber), so you can implement a chat or some other application that needs to push updates to all the connected clients. Though, I must say the only solution supported for PHP is AMF polling. Which means that the client does a request to the server from time to time to see if there is something new. This is a limitation of the PHP servers, as it would be very hard to implement a real data push over an open channel (COMET style maybe?). For example, for Java and ColdFusion servers you can have data pushing using polling or the RTMP protocol.
Secondly, WebORB comes with tons of sample applications, and a console that eases the testing of the services and lets you play with the samples. And finally, using the same console, you can generate some ActionScript code for any service. Basically, it generates a wrapper for the RemoteObject, and an ActionScript object for each of the VO used on the server. However, I didn’t find this to be very helpful, because it doesn’t generate for example the VOAuthor that I used in my example, but instead something like this:
1: package
2: {
3: [Bindable]
4: public class MyServiceModel
5: {
6: public var getDataResult:Object;
7: public var saveDataResult:Object;
8:
9: }
10: }
Queued a Netflix queue manager AIR application
If you live in U.S. and you like to rent movies, then this application will probably be extremely valuable for you. You can download it from here, and read more about it here.
For the rest of us that don’t live in the States, it remains of the theoretical interest in how it was built! It uses Dojo, so it is an AIR application created using HTML/JavaScript/CSS. The source code is available, so you can look at how it was built. Also it uses features from AIR 1.5, such as encrypted local database and update framework. The application was built by SitePen co-sponsored by Adobe.

