Home >
In my first RIA Object Relational Mapping article (see box below) you learned how to transfer the application server’s PHP objects from the server to the Flex client. We accomplished this by using Adobe’s AMF 3 messaging protocol for the client-to-server transfer while preserving the object structure on both platforms (a.k.a. “object relational mapping”). We also covered all the basics of AMF 3 messaging protocol, deploying the Flex client with remote server access, review of server platform alternatives, and selection of the WebORB for PHP application server.
There were so many basic concepts to initially cover that our example showed the transfer from server-to-client of only one simple object. Transferring one simple object at time is not the way the real world works. There are typically hundreds of objects to transfer from the server to the client for information display. That’s what makes an RIA (rich Internet application). Right? With what you know so far, you might think that all you need to do is perform hundreds of single object requests from the server, and voila—later rather than sooner—all of your objects from the server will reside on the Flex client.
Making repeated Flex client single-object data requests to the server is not the way to go. Why, you might ask? Well, it’s slow to say nothing about being highly inefficient. Real work means requesting lots of data objects from the server with one request to the server. These requests are returned as an array. Lets see if we can preserve the object mapping as we move an array of objects from the server to the client. This is what the balance of this article is all about—doing “real” server-to-client work.
Overview
My first RIA Object Relational Mapping article covers object-relational mapping basics and transferring data objects from the client to the server—while preserving the object’s data structure using object relational mapping.
For some server details, see Server Platform Summary in my first RIA Object Relational Mapping article.
If you are unable to deploy the client and server platforms at this time, I do suggest that you continue reading. You’ll become aware that developing rich clients using Adobe Flex Builder IDE and resourcing information from open-source server is actually straightforward to implement once the client and server platforms are in place and you have some core understanding of client-server remoting from this article.
This article and the accompanying client and server example code show you how to transfer the same Family object—from first RIA Object Relational Mapping article—as arrays of object data from the client to the server. We still need to preserve the server-to-client object mapping. This article’s client-side discussion is about client-object mapping when the objects are received as an array.
The source of these server data objects is from a MySQL relational database repository. We’ll discuss all the server’s object creation and packaging as an array for transferring to the Flex client using the Adobe AMF 3 protocol.
Using a PHP object on the application server, we’ll read information from the database repository, transform the data into an object array, and send this data on its merry way to the Flex client. The Flex client will understand the object structure of the received data array and be able extract the object’s properties for convenient user viewing.
Following, we review the client and server example code, some RIA debugging tips, and finally how to deploy this article's example code into your Flex client and PHP-based application server. As a basis for moving ahead with the following discussion, first start with a review of the topics Remoting Protocol Summary, Server Platform Summary, and About AMF 3 in my first RIA Object Relational Mapping article.
Requirements
In order to make the most of this article, you need the following software and files:
Adobe Flex Builder 3 (includes the Flex 3 SDK)
• Try - 60 days (http://www.adobe.com/cfusion/tdrc/index.cfm?product=flex)
• Buy (http://www.adobe.com/go/buyflexbuilder_std)
PHP (workstation, not server, deployment preferred)
• PHP 5.x Scripting Language (http://www.php.net)
Web Server (workstation, not server, deployment preferred)
• Apache HTTP Server (http://httpd.apache.org)
• Alternately Microsoft IIS (preinstalled with Windows XP Professional)
Web Application Server (workstation, not server, deployment preferred)
• WebORB for PHP from Midnight Coders
(http://www.themidnightcoders.com/weborb/php)
Web Debugging Proxy (Optional tool. Use is highly recommended)
• Charles (http://www.charlesproxy.com)
• ServiceCapture (http://kevinlangdon.com/serviceCapture)
Example files
• FamiliesSource.zip (ZIP, 1MB)
| Note: | For Windows development, you can install the WampServer (Apache, PHP, MySQL on Windows) as an all-in-one development server package. (http://www.wampserver.com/en) |
| Note: | Apple’s OS X operating system provides the Apache Web server and PHP. You still need to install the WebORB for PHP application server into the Apache Web server root folder. Installation details follow later in this article. |
Object Relational Mapping of ActionScript and PHP Classes
Figure 1 shows the ActionScript 3 and PHP classes that respectively reside on the Flex client and WebORB PHP server. Each class is written in the respective native development language, ActionScript 3 for the client and PHP for the server.

On both sides of our example solution, our “Family” class consists of an object data structure containing a father, mother, and array of children. These three properties’ data types are of Person type consisting of firstName and lastName properties of type string, where the children property is an array of type string. Note that the PHP class does not define the data types because PHP is a type-less language that propagates the data to the appropriate type internally.
The type-less nature of the PHP class makes class inspection less obvious that the firstName and lastName Person class properties are of type string and that father, mother and the children array are of type Person. We’ll see how this looks in the next section as we review the code.
Our code example Flex client will request the Family object’s data from the WebORB for PHP application server. The WebORB application server will serialize the Family PHP object into AMF 3 and transfer the serial stream to the remote Flex client as an ActionScript RemoteObject. The Flex client detects the AMF 3 receipt through ActionScript event processing. The Flex client receives the data, and de-serializes and maps the data to the Family as ActionScript object structure shown in the left-hand column of Figure 1.
Before jumping into reviewing the code’s operation we need to discuss one important design and development practice. The client and server “Family” and “Person” classes are disparate from each other. That is, each side is incapable of detecting the other side’s differences in data structure or data types. If the data structure and data type do not 100% match, then the server-to-client object data structure will not map, or you may receive a RemoteObject runtime error on the AMF3 receiver during the AMF 3 receive event processing.
When performing code refactoring, which affects the respective client or server class data structure or data type, be sure to also immediately make the change in the opposite side’s class. Failure to keep these classes in sync creates unnecessary runtime errors creating a distracting debug cycle where the actual task at hand is getting real development work done.
Families Example Code Review Summary
If you prefer, you can first install both the example Flex client and PHP server example code. The installation details follow in the Deploying the Flex Client and PHP Server Example Code section.
We have two sets of example code to review. One set for the Flex client, with the second set residing on the WebORB for PHP application server. The code sets work in unison. We’ll cover them separately and link their operations together.
In my first RIA Object Relational Mapping article we purposely provided a very simple application built specifically to demonstrate Flex client/server object-relational mapping. This article’s example code builds on the first article in that the server and client objects are identical to my first RIA Object Relational Mapping article. The first article returns one object from the PHP application server to the Flex client using AMF 3 RemoteObject transfer. We new get a little braver in order to show how to transfer and display an array of objects from the PHP application server to the Flex client.
Figure 2a and 2b shows the result of loading and running the Families application. Figure 2a is the application’s starting display.

When the getFamilies button is clicked the Family Flex client requests the family information from the WebORB for PHP server. The server serializes the family information in AMF 3 and returns the serial stream to the Family Flex client. Upon AMF 3 receipt, an ActionScript 3 event is created, which deserializes the AMF 3 stream and displays the family data as shown in the right side of Figure 2b.

The above two views are all that occurs with our Families example application. There are lots more issues to discuss, related to the underlying code and how the Families Flex client and application server code works. Next, we’ll dig into the code’s operation to master transferring arrays of objects from the PHP application server to the Flex client via AMF 3 remoting.
Families Flex Client Example Code Review
We’ll start by reviewing the Flex client code in the “index.mxml” module. The mxml code for the Families application’s display is between lines 88 and 108. We won’t be discussing this code except to say that line 91 contains a getFamilies button that, when clicked, requests family data from the WebORB PHP application server. Note also that line 90 contains a Clear button to so you can run the server-to-client remote object transfer again.
Deploying the Flex Client and PHP Server Example Code
In my first RIA Object Relational Mapping article, I covered how to set up a Flex RemoteObject connection to the PHP application server using a MXML RemoteObject (<mx:RemoteObject>). There is another way to create the Flex client code by writing the RemoteObject connection using ActionScript 3. In our Families Flex client code example, we’ll show how to set up the RemoteObject connection using ActionScript 3 code.
Before we delve into this RemoteObject code, I suggest that you make yourself aware of the Adobe documentation on this topic:
- Adobe® Flex® 3 Help LiveDocs, Using RemoteObject components
- Adobe® Flex® 3 Language Reference, RemoteObject APIs
- http://livedocs.adobe.com/flex/3/langref/mx/rpc/remoting/mxml/RemoteObject.html
- http://livedocs.adobe.com/flex/3/langref/mx/rpc/remoting/RemoteObject.html
- Establishment of the Flex client RemoteObject connection during the Flex client application initialize time.
- We want the RemoteObject connection to the PHP Web application server to be up and ready before client-to-server messaging is needed.
- The ActionScript 3 mouse "click handler" code, which allows the Flex client to request the data from the PHP application server.
- The ActionScript event handler to process the requested data from the PHP application server to the Flex client using AMF 3 messaging via the RemoteObject connection.
We'll look at the establishment of our RemoteObject ActionScript 3 code through three separate ActionScript 3 RemoteObject elements. These elements are:
Initialize the Flex RemoteObject Connection
Note the Flex client application makes a start-up initialize request at line 4 of “index.mxml” to call the initData ActionScript 3 method at line 37. The initData method, lines 37 to 44 in “index.mxml,” Listing 1, provide instantiation of the RemoteObject object and set the RemoteObject object properties. Our RemoteObject connection between the client and server will last for the life of the Flex client application.
Listing 1 is lines 37 to 44 from the “index.mxml” code module
public function initData():void {
familiesRemote = new RemoteObject();
// Your PHPClassName.php class must be deployed in the WebORB for PHP /Services folder.
// In our case for this client it is: (Web Server Root)/WebORB/Services/MFamiliesDbIO
familiesRemote.destination = "Families";
familiesRemote.getFamilies.addEventListener("result", handlerGetFamilies);
familiesRemote.addEventListener("fault", faultHandler);
}
In the first line in Listing 1, we instantiate our ActionScript 3 RemoteObject object.
Our “Families” Flex Builder project was configured to connect to the WebORB application server located in the “localhost” web server root. These project level connection configuration parameter details are covered in the section Deploying the Flex Client and PHP Server Example Code. The comments, in lines 3 and 4 of Listing 1, identify the path hierarchy in the WebORB for PHP application server running on our “localhost” Web server.
The next RemoteObject property of interest is the destination=“Families” value. The destination value is the name of the PHP object we wish to access on the WebORB for PHP application server. Essentially this is our information repository address on the application server. You’ll see the path to the other side of the RemoteObject connection when we get to the Families WebORB Server Example Code Review section.
Listing 1, lines 6 and 7 establish the event handlers for RemoteObject data received from our PHP application server and secondarily provide a pointer to an ActionScript 3 method to handle received data remote messaging faults.
Adding an event listener, by setting the “familiesRemote.getFamilies.addEventListener("result", handlerGetFamilies)” RemoteObject property establishes the ActionScript 3 event hander to process AMF 3 RemoteObject data from the WebORB PHP application server. Listing 1, line 6 states that if you receive an AMF 3 RemoteObject message from the PHP application server’s “Families” object (Listing 1, line 6), “getFamilies” method (Listing 1, line 6) then pass that message to the Flex client application’s “handlerGetFamilies” method. This is where you will soon see how the received data is bound to pre-defined Flex client objects and processed for display.
The “familiesRemote.addEventListener("fault", faultHandler)” RemoteObject code sets up the ActionScript method to call when the RemoteObject request fails. In our example this ActionScript 3 method is named faultHandler. The method’s task is to display an error dialog containing the RemoteObject communication error message.
Mouse Click Handler Request Data from the Remote Server
Our next requirement is for a way to request data to be sent from the WebORB for PHP server to send data to the client. This is our mouse click handler, which is activated when the user clicks on the getFamilies button, shown above in Figures 2a and 2b.
The ActionScript 3 mouse "click handler" code provides a way for the Flex client to fire a data request to the PHP application server to return the Families data from the server to the client. When the user clicks the getFamiles button, line 91 of "index.mxml", the "handlerClickGetFamilies" ActionScript method, lines 46 to 51 of Listing 2, is called.
Listing 2 is lines 46 to 51 from the “index.mxml” code module
// ------ Handlers ------
private function handlerClickGetFamilies():void {
CursorManager.setBusyCursor();
familiesRemote.getMyFamilies();
trace("handlerClickGetFamilies()");
}
First, it’s a good idea to set the application’s cursor to busy so that the user is aware that the Flex client is awaiting the server’s response to the client’s data request—line 3 of Listing 2.
The active code in the ActionScript 3 “handlerClickGetFamilies” method is line 4 of Listing 2 where the “familiesRemote” RemoteObject object request call is made to the “getFamilies” object method in the PHP application server. You’ll see how these are linked together (client to server) when we get to our discussion of the Families WebORB Server Example Code Review section. For now, accept that this will link the client and server together and RemoteObject messaging will work.
Line 5 of Listing 2 is an optional debug trace statement that can be used when bringing up of the client-to-server AMF 3 message remoting.
The RemoteObject AMF 3 Received Data Handler
When the AMF 4 RemoteObject connection was initialized, Listing 1, the message “result” event handler was set up in line 42 of “index.mxml” in the Flex Builder project to handle RemoteObject messaging events from the PHP application server.
Our RemoteObject event handler method code is shown in Listing 3. After the transfer of the AMF 3 RemoteObject is complete the Flex client activates a “ResultEvent” event, which calls the “handlerGetFamilies” method to process the received data.
Listing 3 is lines 57 to 75 from the “index.mxml” code module
// Families remote object event handler
private function handlerGetFamilies(event:ResultEvent):void {
var i:int = 0;
var parents:Object;
CursorManager.removeBusyCursor();
familiesObjArray = ArrayUtil.toArray(event.result);
familiesObjArrayCollection = new ArrayCollection(familiesObjArray);
// Following 'for each' loop remaps the "familiesObjArray" in mx:DataGrid id="familes"
parentsObjArray = new Array(familiesObjArray.length);
for each (var family:Family in familiesObjArray) {
parents = new Object();
parents.fatherFirstName = family.father.firstName;
parents.fatherLastName = family.father.lastName;
parents.motherFirstName = family.mother.firstName;
parents.motherLastName = family.mother.lastName;
parentsObjArray[i++] = parents;
}
}
Line 5 in Listing 3 removes the busy cursor, which was set by the mouse click handler requesting data from the PHP application server—i.e. server-to-client AMF 3 data transfer is complete.
The “event:ResultEvent” parameter passed into the Listing 3 event handler is an array of “Family” objects. See Figure 1 for the “Family” object data structure. Line 6 transfers the event results into a working and array property named “familiesObjArray.” Figure 3 is a Flex Builder debugger view of the “familiesObjArray” content—an array of Family objects—partially expanded.

Listing 3, lines 8 to 16, remaps the “familiesObjArray” data for a more convenient DataGrid display rendered by lines 93 to 100 of “index.mxml.”
The balance of the code in “index.mxml” is application support code. I do not discuss the Flex client supporting code in this article.
Families WebORB Server Example Code Review
Our WebORB for PHP application server code server nominally resides in the root of your Web server (the “htdocs” folder with Apache’s HTTP Server and “Inetpub\wwwroot” folder with Microsoft’s IIS). The WebORB for PHP server-side code of interest is deployed in WebORB’s “Services” folder containing a folder named “MFamilies.” For a visual perspective of the WebORB for PHP application server deployment see Figure 6. Application Server Software Deployment Hierarchy.
The—one might say the only—PHP module of interest is the “Families.php” object file in WebORB’s “Services” folder. When the “Families” Flex client makes an AMF 3 RemoteObject request to the WebORB server, it’s the “Families.php” object module that is instantiated by WebORB to perform the data acquisition and AMF 3 remote object transfer to the Flex client.
By now, you are probably wondering where the linkage between the client and server occurs to have the Flex client call the “Families.php” object file. Hang on, and we’ll cover this in some detail in the next section.
“Family.php” and “Person.php” modules are object definitions required by “Families.php” to structure and return an array of objects to the Flex client. See Figure 1. Family Classes, Client and Server for the structure details of these two supporting objects.
When “Families.php” is instantiated by the WebORB application server, the object construction module establishes a database connection to the “Families” MySQL database that supports two tables of data: “parents” and “children.”
After the class instantiation to an object, the “getFamilies” method is called. The method:
- Reads the “parents” table data from the “Families” MySQL database.
- Reads the “children” table data from the “Families” MySQL database.
- Packages each database record into a “Family” object.
- Bundles the database record-level “Family” objects into an array.
- Returns the array to the WebORB application server for serializing into an AMF 3 data stream, which is returned to the Flex client and de-serialized for display.
The “FamliesTest.php” PHP module is used for stand-alone testing of the “Families.php” object for proper operation prior to sever-to-client RemoteObject messaging. The same is true for the “FamilyTest.php” module. It’s there for stand-alone operation of instantiating the “Family.php” module’s object.
“Famlies.sql” is the MySQL schema data used to populate the MySQL database with server-to-client test data. This MySQL database schema file does not need to reside here. It was simply placed here for convenience of packaging the “Family” code.
RemoteObject Linkage of the Flex Client to WebORB Services PHP Object
The linkage code in the Flex client and server provides a direct connection between the two disparate elements using a RemoteObject connection. At a top-level view, we must:
- Provide an addressing scheme between the client and server, as neither element is aware of the other’s existence as they are being developed/deployed.
- Provide a mapping scheme where the client’s data request accesses the appropriate PHP method residing in WebORB’s Services—in our environment, the “Family.php” object module.
Client/Server Addressing Scheme
When your Flex Builder project properties are established, we establish where the Flex client is built--and operates--on the Web server relative to where the WebORB for PHP server resides. We then install a custom PHP module in the Flex client folder that points, on a relative data path basis, to the WebORB server. The standard and consistent name for the file for all Flex client builds is “weborp.php.”
The specifics of how to establish this connection are covered in the upcoming section, Deploying the Flex Client and PHP Server Example Code.
Client/Server RemoteObject Messaging Mapping Scheme
Next, let’s discuss how the client-to-server connection mapping is established. Remember our goal is that the “Families” Flex client must connect specifically—and only—to the “FamilyTest.php” module in WebORB’s application server “Services” folder.
Some of the Flex Builder “Families” project parameters discussed next were established when the project’s Flex Builder client and WebORB application server were deployed. For these details see the following section, Deploying the Flex Client and PHP Server Example Code. Also, you might want to follow along with Figure 6. Application Server Software Deployment Hierarchy in order to visualize where these ActionScript 3 RemoteObject parameters are established.
- The “Families” Flex Builder project’s “Additional compiler arguments” is set to access WebORB application server’s “services-config.xml” file, as follows: -services "C:\AMP\Apache\htdocs\WebORB \Weborb\WEB-INF\flex\services-config.xml"
- WebORB’s “services-config.xml” file contains a “destination” entry mapping (linking) to our “Families.php” Services object. See step #5, Figure 7, in the Deploying the Flex Client and PHP Server Example Code section to review the XML destination element values. The destination linkage is Families:MFamilies.Families. (“Families” destination name maps to WebORB “Services” folder containing the “MFamlies” folder that contains the “Families” PHP object with a file name of “Families.php”.)
- Our “Families” Flex client (running in the Web server root) contains a file named “weborb.php” that includes to a file in the WebORB application server that provides a relative path linkage between the Flex client and WebORB application server: require_once("../WebORB/Weborb/ORBHttpHandler.php");
- The “Families” client’s application module (“index.mxml”) sets the ActionScript 3 RemoteObject destination to “Families.” See line 5 of Listing 1: “familiesRemote.destination = "Families”. Accordingly, the Flex client’s RemoteObject connection is inexorably linked to WebORB’s “Families.php” in the “Services” folder. (Item 2, above Families:MFamilies.Families)
In summary, our Flex client is RemoteObject linked to the WebORB application server via the linkage mappings covered in the above four steps.
Deploying the Flex Client and PHP Server Example Code
The Magic of Server-to-client Object Mapping
Earlier in Figure 1. Family Classes, Client and Server we observed that both the Flex client and WebORB application server used identical structures “Family” and “Person” classes slightly different in syntax to support the local native programming language. The native programming language is ActionScript 3 for the Flex client and PHP for the WebORB application server.
Again, I must state that these identical object structures are not a programming accident. The were purposely and carefully selected to be identical so that disparate platform objects match form, fit, and function when ActionScript 3 RemoteObject is transferred between the server and client.
Then later, in Figure 3. “FamiliesObjArray” Array of Family Objects, we noted that the Flex client received the RemoteObject array and magically recognized that the received data was an array of “Family” objects consisting of “Person” and “Children” object properties. Let’s analyze how and why this server-to-client object mapping occurs.
From the “Families.php” class residing in the WebORB application server an array of “Family” objects is serialized as an AMF 3 RemoteObject that is transferred is structured, captured by the Charles Web debugging proxy, as shown in Figure 4.

Figure 4 displays the server-to-Flex client RemoteObject data transfer. Note that the objects returned are a value of “MFamilies.Family” This object value is set by the WebORB application server on the basis of the sequence:
- The Flex client request to the “getFamiles” method in WebORB’s application server
- That, in turns calls the “Families” PHP object module contained the file within WebORB application server located in the folder: “~/WebORB/Services/MFamilies/Families.php .”
- Identifying that a “Family” object is being returned from the “MFamiles” object container folder, i.e. “MFamilies.Family”
As the above-received AMF 3 data stream is being de-serialized, the Flex client’s remote object recognizes that the 10 returned objects are of a type “MFamilies.Familes” (the folder / PHP file name returning the RemoteObject data).
This object recognition (server-to-client mapping) occurs because of the “Family” and “Person” objects defined within the “Families” Flex Builder project. The ActionScript 3 object definitions are located in the project’s “objmaps” folder and shown in Listing 4.
________________________________________
File: Family.as
package objmaps {
import objmaps.Person;
[Bindable]
[RemoteClass(alias="MFamilies.Family")]
public class Family {
// Constructor
public function Family() {}
public var father:Person;
public var mother:Person;
public var children:Array;
}
}
_________________________________________
File: Person.as
package objmaps {
[Bindable]
[RemoteClass(alias="MFamilies.Person")]
public class Person {
// Constructor
public function Person() {}
public var firstName:String;
public var lastName:String;
}
}
Note in Listing 4 that both object definitions (“Family.as” and “Person.as”) have been set as Bindable Remote Classes, with respective aliases of “MFamilies.Family” and “MFamilies.Person.” When our Flex client receives the AMF 3 RemoteObject data stream array from the WebORB application server, the Flex client identifies the Type = “Object” with Value = “MFamilies.Family” and Type = “Object” with Value = “MFamilies.Person” (Figure 4). Flex respectively binds the received objects to be of type “Family” and “Person” objects (Listing 4).
This is how the magic—well it’s not really magic—of client-to-server object mapping occurs. And the mapping consistently and conveniently works for arrays of AMF 3 RemoteObjects too.More On RIA Debugging Tips
First review my first RIA Object Relational Mapping article (http://www.insideria.com/2008/04/amf3-php-server-objects-to-fle.html). In the section RIA Debugging Tips, there’s a plethora of RIA debugging tips and procedures that I do not duplicate in this article.
I continue to support that it’s mandatory to do standalone testing of objects residing in the WebORB for PHP application server prior to server-to-client integration. What I discuss next is the same procedures as described in my first RIA Object Relational Mapping article. The exception being that 1) the name of the two PHP object test modules are different and 2), of course, the resulting data output is different.
Standalone Testing of the Families PHP Object
The WebORB application server will return an array of “Family” objects to the Flex client. Before returning an array of “Family” objects we must first determine that one “Family” object can be properly instantiated. “Family” objects consist as a set of “Person” objects. Our test here first instantiates necessary “Person” objects and then combines the “Person” objects into a “Family” object.
For our “Family” WebORB PHP server object testing you will find a file named “FamilyTest.php.” See Listing 5. We’ll run this test stub code against the “Person” and “Family” PHP objects using the PHP CLI (command line interface) scripting engine. Our “FamilyTest.php” test stub instantiates a father and mother as “Person” objects, lines 4 and 5 of Listing 5. Following these objects instations, an array of children as an array of “Person” objects is generated, line 6 of Listing 5.
Finally the “Family” object is instantiated using our “Person” objects of father, mother and the children array, line 8 of Listing 5.
require_once("Person.php");
require_once("Family.php");
$father = new Person('Sam', 'Blackburn');
$mother = new Person('Barbara', 'Blackburn');
$children = Array(new Person('Robert','Blackburn'), new Person('Lisa','Blackburn'), new Person('Charles','Blackburn'));
$familyObj = new Family($father, $mother, $children);
echo "-------------------\nFather and Mother Person Objects, and Children as an Array of Person Objects:\n";
echo "\n\$father: "; print_r($father);
echo "\n\$mother: "; print_r($mother);
echo "\n\$children: "; print_r($children);
echo "\n-------------------\nThat get combined into a \"Family\" Object, like this:\n\n";
echo "\$familyObj as Array:\n"; print_r($familyObj);
echo "\n-------------------\nAnd this....\n\n";
echo "\$familyObj as Object:\n"; var_dump($familyObj)
Lines 10 through 17 of Listing 5 output our individual and combined objects shown next. We now know that we can create one “Family” object. The next section, Standalone Testing of the Families PHP Objects, will show you how to verify the proper operation of creating an array of “Family” objects.
Output from running the Listing 5's "FamilyTest.php" code:
-------------------
Father and Mother Person Objects, and Children as an Array of Person Objects:
$father: Person Object
(
[firstName] => Sam
[lastName] => Blackburn
)
$mother: Person Object
(
[firstName] => Barbara
[lastName] => Blackburn
)
$children: Array
(
[0] => Person Object
(
[firstName] => Robert
[lastName] => Blackburn
)
[1] => Person Object
(
[firstName] => Lisa
[lastName] => Blackburn
)
[2] => Person Object
(
[firstName] => Charles
[lastName] => Blackburn
)
)
-------------------
That get combined into a "Family" Object, like this:
$familyObj as Array:
Family Object
(
[father] => Person Object
(
[firstName] => Sam
[lastName] => Blackburn
)
[mother] => Person Object
(
[firstName] => Barbara
[lastName] => Blackburn
)
[children] => Array
(
[0] => Person Object
(
[firstName] => Robert
[lastName] => Blackburn
)
[1] => Person Object
(
[firstName] => Lisa
[lastName] => Blackburn
)
[2] => Person Object
(
[firstName] => Charles
[lastName] => Blackburn
)
)
)
-------------------
And this....
$familyObj as Object:
object(Family)#6 (3) {
["father"]=>
object(Person)#1 (2) {
["firstName"]=>
string(3) "Sam"
["lastName"]=>
string(9) "Blackburn"
}
["mother"]=>
object(Person)#2 (2) {
["firstName"]=>
string(7) "Barbara"
["lastName"]=>
string(9) "Blackburn"
}
["children"]=>
array(3) {
[0]=>
object(Person)#3 (2) {
["firstName"]=>
string(6) "Robert"
["lastName"]=>
string(9) "Blackburn"
}
[1]=>
object(Person)#4 (2) {
["firstName"]=>
string(4) "Lisa"
["lastName"]=>
string(9) "Blackburn"
}
[2]=>
object(Person)#5 (2) {
["firstName"]=>
string(7) "Charles"
["lastName"]=>
string(9) "Blackburn"
}
}
}
Standalone Testing of the Families PHP Objects
For our “Families” WebORB PHP server object you will find a file named “FamiliesTest.php.” See Listing 6. I run this test stub code against the “Families” PHP objects using the PHP CLI (command line interface) scripting engine. The test first instantiates the “Families” object and then returns an array of “Family” objects by using the ““Families” object pointer by calling the “getFamilies” method.
require_once("Families.php");
try {
$familes = new Families(); // Instantiate the MyFamilies class, and...
$familyArray = $familes->getFamilies(); // create the array of Family objects.
echo "\$familyArray Return:\n";
echo " Note: Following is the Family object array of that will be returned to your Flex client.\n\n";
var_dump($familyArray);
echo "\n";
} catch (Exception $exception) {
printf("%s\n", $exception->getMessage());
}
echo "'FamiliesTest.php' Object Test Call Complete.\n";
Next the “FamiliesTest.php” dumps the data as an array of data (“var_dump” function). Listing 5 shows the test results as an array of “Families” objects. I observe that the data output is as we expect it to be.
Output from running the Listing 6's "FamiliesTest.php" code:
$familyArray Return:
Note: Following is the Family object array of that will be returned to your Flex client.
array(10) {
[0]=>
object(Family)#8 (3) {
["father"]=>
object(Person)#9 (2) {
["firstName"]=>
string(3) "Sam"
["lastName"]=>
string(9) "Blackburn"
}
["mother"]=>
object(Person)#10 (2) {
["firstName"]=>
string(7) "Barbara"
["lastName"]=>
string(9) "Blackburn"
}
["children"]=>
array(3) {
[0]=>
object(Person)#5 (2) {
["firstName"]=>
string(6) "Robert"
["lastName"]=>
string(9) "Blackburn"
}
[1]=>
object(Person)#6 (2) {
["firstName"]=>
string(4) "Lisa"
["lastName"]=>
string(9) "Blackburn"
}
[2]=>
object(Person)#7 (2) {
["firstName"]=>
string(7) "Charles"
["lastName"]=>
string(9) "Blackburn"
}
}
}
[1]=>
object(Family)#13 (3) {
["father"]=>
object(Person)#14 (2) {
["firstName"]=>
string(7) "Richard"
["lastName"]=>
string(5) "Weiss"
}
["mother"]=>
object(Person)#15 (2) {
["firstName"]=>
string(5) "Alice"
["lastName"]=>
string(5) "Weiss"
}
["children"]=>
array(2) {
[0]=>
object(Person)#4 (2) {
["firstName"]=>
string(5) "Terry"
["lastName"]=>
string(5) "Weiss"
}
[1]=>
object(Person)#12 (2) {
["firstName"]=>
string(4) "Mike"
["lastName"]=>
string(5) "Weiss"
}
}
}
[2]=>
object(Family)#17 (3) {
["father"]=>
object(Person)#18 (2) {
["firstName"]=>
string(6) "Joesph"
["lastName"]=>
string(5) "Adams"
}
["mother"]=>
object(Person)#19 (2) {
["firstName"]=>
string(7) "Shirley"
["lastName"]=>
string(5) "Adams"
}
["children"]=>
array(1) {
[0]=>
object(Person)#11 (2) {
["firstName"]=>
string(8) "Jonathan"
["lastName"]=>
string(5) "Adams"
}
}
}
[3]=>
object(Family)#24 (3) {
["father"]=>
object(Person)#25 (2) {
["firstName"]=>
string(4) "Gail"
["lastName"]=>
string(6) "Hayden"
}
["mother"]=>
object(Person)#26 (2) {
["firstName"]=>
string(4) "Mary"
["lastName"]=>
string(6) "Hayden"
}
["children"]=>
array(4) {
[0]=>
object(Person)#16 (2) {
["firstName"]=>
string(3) "Jim"
["lastName"]=>
string(6) "Hayden"
}
[1]=>
object(Person)#21 (2) {
["firstName"]=>
string(5) "Carol"
["lastName"]=>
string(6) "Hayden"
}
[2]=>
object(Person)#22 (2) {
["firstName"]=>
string(6) "Marcia"
["lastName"]=>
string(6) "Hayden"
}
[3]=>
object(Person)#23 (2) {
["firstName"]=>
string(5) "Doris"
["lastName"]=>
string(6) "Hayden"
}
}
}
[4]=>
object(Family)#20 (3) {
["father"]=>
object(Person)#28 (2) {
["firstName"]=>
string(5) "Larry"
["lastName"]=>
string(5) "Lyman"
}
["mother"]=>
object(Person)#29 (2) {
["firstName"]=>
string(7) "Beverly"
["lastName"]=>
string(5) "Lyman"
}
["children"]=>
array(0) {
}
}
[5]=>
object(Family)#31 (3) {
["father"]=>
object(Person)#32 (2) {
["firstName"]=>
string(5) "James"
["lastName"]=>
string(7) "Raphson"
}
["mother"]=>
object(Person)#33 (2) {
["firstName"]=>
string(4) "Lois"
["lastName"]=>
string(7) "Raphson"
}
["children"]=>
array(1) {
[0]=>
object(Person)#27 (2) {
["firstName"]=>
string(4) "Alan"
["lastName"]=>
string(7) "Raphson"
}
}
}
[6]=>
object(Family)#37 (3) {
["father"]=>
object(Person)#38 (2) {
["firstName"]=>
string(4) "Mark"
["lastName"]=>
string(6) "Kendal"
}
["mother"]=>
object(Person)#39 (2) {
["firstName"]=>
string(6) "Shelly"
["lastName"]=>
string(6) "Kendal"
}
["children"]=>
array(3) {
[0]=>
object(Person)#30 (2) {
["firstName"]=>
string(4) "Gene"
["lastName"]=>
string(6) "Kendal"
}
[1]=>
object(Person)#35 (2) {
["firstName"]=>
string(4) "Earl"
["lastName"]=>
string(6) "Kendal"
}
[2]=>
object(Person)#36 (2) {
["firstName"]=>
string(8) "Margaret"
["lastName"]=>
string(6) "Kendal"
}
}
}
[7]=>
object(Family)#43 (3) {
["father"]=>
object(Person)#44 (2) {
["firstName"]=>
string(4) "Jack"
["lastName"]=>
string(5) "Young"
}
["mother"]=>
object(Person)#45 (2) {
["firstName"]=>
string(5) "Marge"
["lastName"]=>
string(5) "Young"
}
["children"]=>
array(3) {
[0]=>
object(Person)#34 (2) {
["firstName"]=>
string(7) "Matthew"
["lastName"]=>
string(5) "Young"
}
[1]=>
object(Person)#41 (2) {
["firstName"]=>
string(5) "Judie"
["lastName"]=>
string(5) "Young"
}
[2]=>
object(Person)#42 (2) {
["firstName"]=>
string(6) "Harold"
["lastName"]=>
string(5) "Young"
}
}
}
[8]=>
object(Family)#51 (3) {
["father"]=>
object(Person)#52 (2) {
["firstName"]=>
string(4) "Bill"
["lastName"]=>
string(5) "Moran"
}
["mother"]=>
object(Person)#53 (2) {
["firstName"]=>
string(7) "Dorothy"
["lastName"]=>
string(5) "Moran"
}
["children"]=>
array(5) {
[0]=>
object(Person)#40 (2) {
["firstName"]=>
string(5) "Duane"
["lastName"]=>
string(5) "Moran"
}
[1]=>
object(Person)#47 (2) {
["firstName"]=>
string(4) "Jeff"
["lastName"]=>
string(5) "Moran"
}
[2]=>
object(Person)#48 (2) {
["firstName"]=>
string(5) "Helen"
["lastName"]=>
string(5) "Moran"
}
[3]=>
object(Person)#49 (2) {
["firstName"]=>
string(3) "Jim"
["lastName"]=>
string(6) "Fisher"
}
[4]=>
object(Person)#50 (2) {
["firstName"]=>
string(5) "Sally"
["lastName"]=>
string(6) "Fisher"
}
}
}
[9]=>
object(Family)#56 (3) {
["father"]=>
object(Person)#57 (2) {
["firstName"]=>
string(3) "Bob"
["lastName"]=>
string(6) "Harris"
}
["mother"]=>
object(Person)#58 (2) {
["firstName"]=>
string(7) "Sherril"
["lastName"]=>
string(6) "Harris"
}
["children"]=>
array(2) {
[0]=>
object(Person)#46 (2) {
["firstName"]=>
string(5) "Megan"
["lastName"]=>
string(6) "Harris"
}
[1]=>
object(Person)#55 (2) {
["firstName"]=>
string(5) "Ralph"
["lastName"]=>
string(6) "Harris"
}
}
}
}
'FamiliesTest.php' Object Test Call Complete.
We’ve learned that our WebORB application server’s object returns are working as expected. This assures us that the data to be returned from the server to the Flex client is proper as we get ready to perform RemoteObject server to Flex client messaging.
Debugging PHP code when invoked from Flex Client
One of the most frustrating things in PHP is the complete lack of normal debugging tools. As a result, when PHP is invoked from a rich client like Flex, one must get very creative in order to tap into the PHP invocation flow and debug it. Traditional PHP use of echo or print statements do not work because any debug output is not visible because there is no output console available.
For more details on what can be done in the way of clever debugging procedures within the WebORB’s application server see Mark Plller’s blog at: ( http://www.themidnightcoders.com/blog/2008/09/debugging-php-code-when-invoked-from.html ) I think you will find this debugging article a valuable and interesting insight of lesser known debugging procedures.
Deploying the Flex Client and PHP Server Example Code

Note: this “Families” deploy section assumes that you have already pre-installed your AMP server (Apache or MS IIS Web server), MySQL (optional), and PHP scripting engine.
1. Download and install WebORB for PHP into your (nominally Apache) web server root folder. Follow the WebORB for PHP installation and configuration instructions found in the Midnight Coders Web site at Getting Started with Flex and WebORB for PHP ( http://www.themidnightcoders.com/weborb/php/gettingstarted.htm ). Place the WebORB root folder in your Web server root folder as shown in Figure 6. Test WebORB for PHP operation by entering the following in your Web browser: http://localhost/WebORB/.
2. Download and unzip the “FamiliesSource.zip” file identified at the start of this article. There are three folders of files to install. One folder is installed inside the WebORB for PHP server; the second folder is a pre-compiled version of the “Families” example; the third folder is the Flex Builder client project.
- “MFamilies” folder for WebORB for PHP installs in the “Services” folder
- “Families” - The “Families” folder installs the root of your Web server folder as shown in Figure 6.
- “Families Flex Builder Source” folder
3. Copy (or move) the “MFamilies” (not “Families”) folder into the “WebORB /Services” folder as shown in Figure 6.
4. Using the “Families.sql” SQL schema file create the “Families” database, the “children” and “famil”` database tables, load the “Families” database content into their respective tables, and set the MySQL database “Grant” (login) access.
5. Configure the MyFamily Flex RPC endpoint in the “remoting-config.xml” file. This XML file is located in the folder path of “WebORB/Weborb/WEB_INF/flex/remoting-config.xml”, as shown in Figure 6. Make the following tag entry addition somewhere in the XML file where the tags reside:

6. Copy the “Families” example Flex client application to your Web server root folder as shown in Figure 6.
Note: At this time you can run and evaluate the “Families” example before you install the example “Families” Flex Builder 3 project. From your Web browser enter the URL: “http://localhost/Families”. This exercise will tell you if your WebORB PHP Web application server is properly installed and configured. Get this working before performing step number 7.
Next, in step 7, you will establish your “Families” Flex Builder 3 project. Note in Figure 6 that the “Families” Flex client resides outside of the WebORB for PHP application server in the Web server root. For access convenience, the WebORB application server, and Flex client deployment it is desirable to deploy the “Families” flex client in the Web Server root.
The Flex Builder 3 New => Flex Project configuration insists that you build and test your project inside of WebORB’s “~/WebORB/Weborb/WEB-INF/flex” folder. Flex Builder 3 does this to the point of not alloying you to complete your project build configuration until you accept building the Flex client within the above folder path within WebORB. When creating a new Flex Builder 3 project, there’s a way around the unnecessary limitation. Inside the “FamiliesSource” zip file folder is a document called “Configure New Flex Builder 3 Project Notes.” It takes you through the steps to build a Flex client outside the confines of your WebORB application server.
7. In the “FamiliesSource” zip file folder is a folder named “Families Flex Builder Source” folder, which contains the Flex Builder 3 source files for the “Families” example. Using the instructions in the “Configure New Flex Builder 3 Project Notes” document, create your “Families” Flex Builder 3 project and install the “Families Flex Builder Source” files. In particular, from the named “Families Flex Builder Source” folder:
- Replace the Flex Builder 3 “index.mxml” file in the Flex Builder project with the “index.mxml” file provided in the “Families Flex Builder Source” folder.
- Copy the “objmaps” folder from the Families Flex Builder Source” folder to the “Families” Flex Builder project’s “src” folder. See Figure 8.





Facebook Application Development
This is great article. i must take a long time to learn this article
according to you, whether weborb is the best option for the use of PHP with Flex?
well Thanks
I was trying to find the best solution for Flex-PHP communication. I evaluated HTTP Requests with XML, AMF-PHP, AMFZend and the "Create a database application" within flex builder.
I ended up using Zend-Amf. Mainly because AMF-PHP would be a good choice, but not officially supported anymore.
Secondly because WebORB is very very powerful, it has a great code generator, does all the mapping, ensures foreign key constraints, etc., but this means a huge amount of code (which you have not written yourself) and the support (community) etc. is not too established yet.
I was afraid to use it and then get lost in the middle of my project.
With ZendAMF you have to write all the class mappings yourself, but the usage is straight forward, and no DataMapper, Wrapper Classes etc. are hidden somewhere.
If you have the time to get around to learn WebORB it would be great, but ZendAMF was my choice. Also it is the official supported communciation from Adobe and Zend.
The flex database application generation is nice, but just useful for one Table at most, because the generated code uses all the same method,class names, etc.
So far,
Martin
Wouldn't it be a lot easier to take advantage of Weborbs built in relation mapping via foreign keys using their code generator? If you are building your app from scratch I see how this article and the sample would be super helpful, but if you've already generated all your php files and class files with WebOrb's tool - it's hard to know how to adjust the code to achieve the same effect you've created here.
Great article however, thanks!
Hi Stacey,
Your question related to using the WebORB code generation is a good one and worthy of some discussion.
First, let me say the for anyone who is new to using WebORB for PHP, I heartily recommend that you use the WebORB for PHP code generation functionality. Truly this capability makes your client / server development task much simpler.
There are several reasons I did not write about using the WebORB for PHP code generation, none, of which, stands out as "the" reason for my manual code generation example. My reasons were:
1. I wrote this article a year ago (May 2008). At that time the released version of WebORB for PHP did not support PHP code generation.
2. I wanted to discuss and demonstrate the manual generation of WebORB PHP Services classes in order for the users to understand and appreciate the code development issues. There's always the requirement to manually tune the generated WebORB PHP Services classes logic and one has to understand the underlying functionality of the generated code. I am a strong believer that developers should not use other people codes--whether its example code or generated code--without first 100% understanding how it operates.
3. I develop software on an iMac 24" OS X, 10.7, Leopard platform. For some reason, which I've been unable to determine, the WebORB for PHP 3.5 code generation refuses to work on this platform. The errors are around not being able to write the generated PHP code modules due to file access security restrictions. Even though I have been working on Unix based platforms for decades, I have yet to determine why the false access security errors are occurring.
4. Lastly, a weak reason only for me. I have using WebORB for PHP for RIA Flex client / server solutions since version 1.0. Accordingly, I can write a WebORB PHP Services classes in a matter of minutes and it will have all the business logic I require coming out of the gate for client / server remoting messaging.
Hope this helps......
Pete Mackie
Great article!
But unfortunately nobody covers the following issue:
Sending back an array of objects (DataProvider of DataGrid) back to the server (php plus flex ).
Thanks in advance
Gerry Hollinka
Great article!
But unfortunately nobody covers the following issue:
Sending back an array of objects (DataProvider of DataGrid) back to the server (php plus flex ).
Thanks in advance
Gerry Hollinka
Hi Gerry,
Passing arrays from your Flex client to your WebORB server is actually quite simple. Its simply the same exercise in reverse. First write an WebORB PHP Service class, with a method that accepts an array. Next, set up a RemoteObject connection on your Flex client. Create an array and pass it to your WebORB PHP Service class via your RemoteObject connection.
If you cannot get this to work, then let me know. I can provide some (very brief) code snippets examples here.
Pete Mackie
Hello Pete thanks for your thoughtful response!
Your article will in fact be helpful for my "fine tuning" - it took some searching on the Flashorb yahoo group to find answers to my questions about how to use related data with Weborb - caramba it's so easy a caveman could do it! Still having a weird problem though, where I cannot get 2 datagrids using the same object or class to load in different views (1 datagrid for each Section coming from the Lessons table in my case) Seems I can load either one datagrid with Lessons and a findBy statement for Section 1, or another datagrid with a findBy statement for Section 2, or the other, but never both - now that is because I used a code generator, and have no clue how these elements are interacting with my app, lol. Will read your article in more detail and I'm sure I'll see the answer to my problem. I saw a couple of other folks on Weborb's forum with a similar issue though, so i do wonder if it's a Weborb thing - something about the way ActiveRecords are dealt with?
Thanks again for your lovely tutorial and I hope to see more Weborb stuff :)
Stacey in Alaska
Stacey,
Yes indeed remoting to/from WebORB is easy enough for a caveman to do. Albeit, you have to first know about the little details, hence the reason for my article.
re below: I used a code generator, and have no clue how these elements are interacting with my app, lol
I have been developing software for over forty years. In the early days we never ever shared our software code with others. Each software development project was a large monolith created by rooms full of developers with lots of duplication of effort by each project. Over the years, the community begin to realize that a good share of the code each project group was developing was common. Slowly, but surely, we started sharing and trading ideas related to the commonly required code on a strictly informal basis.
Over time, code sharing evolved into more formal ways such as the open source movement, blogs where the example code is located by using Web search engines, and with code generation utilities such as WebORB. There becomes a natural tendency to grab these freely available code resources and deploy them into your development project with little or no understanding of how it works or exactly what it is supposed to do.
The next think you know, one is totally dependent upon this "free" code, which required little or now effort to deploy, but now you realize that it is not doing exactly what you planned it would do. Now you must go into the code and expend some effort to understand its operation in order to modify it to me your functional needs. This brings me to my corollary about using freely available example code. And that is one should never use code created by others or generated by utilities without first 100% understanding how it works and how to best apply this code to meet your specific needs. Because, sooner rather that later, you will undoubtedly realize that this code will need modification or enhancement. So master its use during the start of its use and not in the middle of things where you have to back out the code in order to refactor it towards meeting your functional needs.
There is no free lunch by using code created by others, whether it is shared through open source or generated by a utility. There has to be significant investment of time and effort in order to master the use of software code created by others. The code use mastery effort needs to occur at the front-end of deploying code created / generated by others.
Soon there will be a new release of WebORB for PHP with enhanced code generation capability. Once the new WebORB release is available, I plan to better master what is provided and not provided with the generated code produced by WebORB. I'm thinking that I might write another article on how to best tackle the use and application of the WebORB generated code by explaining the traps and pitfalls of using code without understanding its operation. Said another way, how to use generated code to your benefit and not letting this code take you in directions you should not be going.
Pete Mackie
-----------------------------------
On May 24, 2009, at 12:20 AM, mspanish@zoho.com wrote:
> Hello Pete thanks for your thoughtful response!
>
> Your article will in fact be helpful for my "fine tuning" - it took
> some searching on the Flashorb yahoo group to find answers to my
> questions about how to use related data with Weborb - caramba it's so
> easy a caveman could do it! Still having a weird problem though, where
> I cannot get 2 datagrids using the same object or class to load in
> different views (1 datagrid for each Section coming from the Lessons
> table in my case) Seems I can load either one datagrid with Lessons and
> a findBy statement for Section 1, or another datagrid with a findBy
> statement for Section 2, or the other, but never both - now that is
> because I used a code generator, and have no clue how these elements
> are interacting with my app, lol. Will read your article in more detail
> and I'm sure I'll see the answer to my problem. I saw a couple of other
> folks on Weborb's forum with a similar issue though, so i do wonder if
> it's a Weborb thing - something about the way ActiveRecords are dealt
> with?
>
>Thanks again for your lovely tutorial and I hope to see more Weborb
> stuff :)
>
> Stacey in Alaska
Pete,
Thank you for this article, it is very informative. I agree completely about the data management tools that WebORB provides. I also agree that just because it generates code, it does not guarantee to make your life easier. This is true for all tools really, if you don't know how to use a drill what good is it. The bottom line the way I see it is, in theory, you spend some time now learning the tools you can use to make your life easier as long as you can successfully understand its benefits and pitfalls; and of course be able to use the same tools you understand better (hopefully fully) to help you on future projects. All this in the end allowing you to be more efficient in some way.
I recently used Hibernate to do a lot of the ORM lifting for me, while now I can say that I would greatly benefit from using it again, I also have to add that the initial learning curve was steep, and I can still learn a thing or two.
I look forward to your next article of this series.
Best,
Luis
Hi Pete,
Thanks for taking the time.
In the familly class, if I want to strongly type the var children:array, to check that this array contain a well formed person.as, do you recommend to use :
[ArrayElementType("Person")] public var children:Array;
Simon
Hi Simon,
Simon,
Yes, you can indeed to this to guaranteed that the proper data type received. And its a data type management point well taken.
In our case though, through our AMF 3 RemoteObject access we are tightly controlled what is being received from the WebORB application server to the Flex client. Accordingly the is little or not chance for error.
Thanks for pointing out the very important consideration for strong run-time dynamic data type detection.
Pete