Working in Flash Builder 4 with Flex and PHP

On June 1st we launched the public beta for Flash Builder 4, the newest iteration of our Eclipse-based IDE for RIAs, formerly known as Flex Builder 3. While you can find both evolutionary and revolutionary features in it, in this article I will touch on the data features and Flex – PHP integration features of Flash Builder 4.

In this article, I will show you how can you use a PHP class that manages a MySQL table (offering CRUD operations) in a Flex project. I will build the Flex project and I rely on Flash Builder 4 to set up the Zend Framework for me(because I want to use remoting as a way to talk with the PHP server). After this I will use the new wizard from Flash Builder 4 that introspects a PHP class and creates the ActionScript code to consume that PHP class.

In the end I should be able to have a simple Flex app that lets me see the data records, edit them, and add a new item. For some of the features I’ll have to write code, for others Flash Builder will generate the code. All in all, I think the application can be created in less than 30 minutes.

PHP code

I have two PHP classes that I want to reuse with my Flex application. One class is a data object that acts asa wrapper for one row from my database (MySQL). Here is the structure of the table:

id_aut – primary key
fname_aut string
lname_aut string

The PHP data object, called VOAuthor, looks like this:

   1: class VOAuthor {


   3:     public $id_aut;

   4:     public $fname_aut;

   5:     public $lname_aut;

   6: }


The second class, called Authors, is the class that manages the table, offering CRUD operations. The code is very straight forward, I don’t use any database abstraction layer. I have three methods one each for reading, deleting, and updating/inserting a record. I use the data object, VOAuthor, within these methods. This is the code:

   1: require_once 'VOAuthor.php';



   4: //connection info

   5: define("DATABASE_SERVER", "localhost");

   6: define("DATABASE_USERNAME", "mihai");

   7: define("DATABASE_PASSWORD", "mihai");

   8: define("DATABASE_NAME", "flex360");


  10: //$o = new MyService();

  11: //print_r($o->getData());


  13: class Authors {


  15:     /**

  16:      * Retrieve all the records from the table

  17:      * @return an array of VOAuthor

  18:      */

  19:     public function getData() {

  20:         //connect to the database.

  21:         //we could have used an abstracting layer for connecting to the database.

  22:         //for the sake of simplicity, I choose not to.

  23:         $mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD);

  24:         mysql_select_db(DATABASE_NAME);

  25:         //retrieve all rows

  26:         $query = "SELECT id_aut, fname_aut, lname_aut FROM authors_aut ORDER BY fname_aut";

  27:         $result = mysql_query($query);

  28:         //throw (new Zend_Amf_Exception('error', 11));

  29:         $ret = array();

  30:         while ($row = mysql_fetch_object($result, "VOAuthor")) {

  31:             $ret[] = $row;

  32:         }

  33:         mysql_free_result($result); 

  34:         return $ret;

  35:     }

  36:         /**

  37:      * Update one item in the table

  38:      * @param VOAuthor to be updated 

  39:      * @return NULL

  40:      */

  41:     public function saveData($author) {

  42:         if ($author == NULL)

  43:             return NULL;

  44:         //logMe($author);

  45:         //connect to the database.

  46:         $mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD);

  47:         mysql_select_db(DATABASE_NAME);

  48:         if ($author->id_aut > 0) {

  49:             //save changes

  50:             $query = "UPDATE authors_aut SET fname_aut='".$author->fname_aut."', lname_aut='".$author->lname_aut."' WHERE id_aut=".  $author->id_aut;

  51:         } else {

  52:             //add new record

  53:             $query = "INSERT INTO authors_aut (fname_aut, lname_aut) VALUES ('".$author->fname_aut."', '".$author->lname_aut."')";

  54:         }

  55:         $result = mysql_query($query);

  56:         return NULL;

  57:     }


  59:     public function deleteData($author) {

  60:         if ($author == NULL)

  61:             return NULL;


  63:         //connect to the database.

  64:         $mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD);

  65:         mysql_select_db(DATABASE_NAME);

  66:         //add new record

  67:         $query = "DELETE FROM authors_aut WHERE id_aut = ".$author->id_aut;

  68:         $result = mysql_query($query);

  69:         return NULL;

  70:     }


  72: }

These two scripts sit inside of a folder called “remoting” in the root of the Apache web server document root folder.

Creating the Flex project and the UI of the app

I have the PHP files in place; now it’s time to create the Flex application. First, I need to create a new Flex project. Having opened the Flash Builder 4, I use the “New Flex Project” wizard to create a new Flex project called FlexPHPAMF. Make sure that in the wizard you choose PHP as the server technology, and you give the correct information for the document root of the web server (absolute path and URL).

Now let’s create the UI of the application. To do this, I chose to go in design mode where I added two buttons and a data grid to the stage. One button is labeled “Get Data” and the other one “Save Data”.


Using the data service panel

Finally, I am ready to use the new data wizards.At the bottom of Flash Builder, there is a view called “Data/Services”. Click on “Connect to Data/Service” link. A wizard starts, and you can select the type of the data service.


Because I want to use the PHP classes I have, I choose PHP and I click “Next”.


On this page, you can select to either reuse an existing service from the server, or to let the wizard create a stub for you. Because I have the service, I want to use the Import PHP class option. Flash Builder introspects the service in order to detect the supported operations (in this case, because I am using remoting, it detects the public methods and the return type). But to do so, it needs to install the Zend Framework to your web server.

What is very cool is that you don’t have to worry about the steps needed to install Zend Framework. Flash Builder will do it for you automatically.


After the Zend Framework is installed, on the last page of the wizard you’ll see the available methods. Click Finish.


Now, in the Data/Services view you should have a tree, with the root node named Authors. This is the name of the PHP class that you want to use in Flex. Under this node you have Data Types, and the three methods: deleteData(), getData(), saveData().


At the same time if you take a look at the project structure in the Package explorer, you’ll notice that new packages and files were created.


There is a new package called services.authors, and here you’ll find the service class that you’ll use to connect to the PHP class ( This class actually extends a base class that implements all the logic using RemoteObject. The reason for this approach is that when you need to do your customization, you’ll do it in the Authors class. If you decide to use Flash Builder to regenerate the code for the same service (maybe as a result of a change on the server side), this operation will not over write your custom code.

The same goes for the data object (or value object). Flash Builder generated the ActionScript value object to match the PHP class VOAuthor. But again, you might want to do some customizations, and you can do it by touching VOAuthor that extends _Super_VOAuthor. All the generated code stays in the _Super_VOAuthor.

And finally, you’ll find a folder called services that gives you quick access to the Authors.php class.

It is time to fill the data grid with the data from the server. To do so, first you need to make sure that the return type for the getData() operation is an array of VOAuthor objects. If you right click on the name of the operation in the Data/Services view and choose Configure Return Type, you have a way to specify the array of VOAuthor:


To bind the data grid to the result of the getData() operation you have to go into design mode, and then drag and drop the getData() (from the Data/Services view) to the data grid.

If you switch to code view, you’ll see that some ActionScript code was added to the flexPHPAMF.mxml. What you want to do is to grab the line from the function and create a new function that will be called when you click the “Get Data” button and paste the code inside of it. My code looks like this:

   1: protected function getData():void

   2: {

   3:    getDataResult.token = authors.getData();

   4: }

   5: [...]


   7: <s:Button x="43" y="220" label="Get Data" click="getData()"/>

The wizard altered the data grid itself, you have the name of the table fields as labels, and the data provider of the data grid is set to the lastResult of the getDataResult object (this object was added to your code by the wizard, in order to help you manage the results of the authors service).

If you run the application and press the “Get Data” button, you should see the data.

Adding editing capabilities

The final part of this tutorial is adding the editing capabilities. I want to be able to edit an existing record using the data grid itself, and I want to have a form and a new button. First go back into design mode, drag and drop an new button on the stage, and change the label to “New”. Then, you’ll use another wizard to generate the form for editing. To do so, you select from the Data/Services view the Data Types node, expand it, and select the VOAuthor node. Right click it and select Generate Form. In the wizard choose “Make form editable” and click Next.


In the second page of the wizard deselect the “id_aut” property. This value will be auto-inserted by the database itself. Click Finish.


After the form is generated, you want to grab the form and position it maybe below the buttons. Also, you may want to change the labels. Finally add a new button in the form and label it “Add”.

Switch back to code view. Now, you need to make some changes. First of all (I think it is a bug), the text fields are not editable (they are Text instead of TextInput). So change the type to TextInput to make them editable. Next, give an ID to the Form itself. I want to have the form invisible when the application is loaded, and only make it visible when the users clicks “New”. For that you set the visible property on the form to false, and you add some code to the New button. Here is my code:

   1: <s:Button x="224" y="220" label="New" click="myForm.visible = true"/>

   2: <mx:Form x="46" y="277" id="myForm" visible="false">

   3:         <mx:FormItem label="First Name:">

   4:             <mx:TextInput id="fname" text=""/>

   5:         </mx:FormItem>

   6:         <mx:FormItem label="Last Name:">

   7:             <mx:TextInput id="lname" text=""/>

   8:         </mx:FormItem>

   9:         <mx:FormItem>

  10:             <s:Button label="Add"/>

  11:         </mx:FormItem>

  12: </mx:Form>

And if you look in the code, you’ll notice a new object was created:

   1: <authors:VOAuthor id="vOAuthor"/>

You’ll use this instance of the value object VOAuthor to send the new item to the server (remember, the PHP saveData() method expects a single argument of type VOAuthor).

To do so, you need to create a binding between the two text fields from the form and the properties fname_aut and lname_aut of the VOAuthor.

   1: <fx:Binding destination="vOAuthor.fname_aut" source="fname.text"/>

   2: <fx:Binding destination="vOAuthor.lname_aut" source="lname.text"/>

The last missing piece is the actual call to the saveData() method. This is very simple;on the click event of the “Save” button you add the call to the authors object getData() method, passing the local instance of VOAuthor (vOAuthor) as the argument:

   1: <s:Button label="Add" click="authors.saveData(vOAuthor)"/>

You can add a new record now. What about editing an existing one? For this we will need a little bit more code. First, you want to register a listener on the data grid in order to know when something was edited (if you set the property editable to true on the data grid, then you can edit information inline). The event you are looking for is itemEditEnd:

   1: <mx:DataGrid x="44" y="37" id="dataGrid" dataProvider="{getDataResult.lastResult}" 

   2:         itemEditEnd="dataEdited(event)" editable="true">

Now,let’s define the listener, dataEdited(). Add the following code in the script section of the page:

   1: private function dataEdited(event: DataGridEvent):void 

   2: {

   3:      vOAuthor = as VOAuthor;

   4: }

This code uses the instance of the value object VOAuthor to store the data used by the edited row.

The last two things you have to do is to create a function called saveData() that is called when the user clicks the “Save Data” button, and to add initialization code for the vOAuthor object when the users clicks the “New” button (this way you avoid updating an item instead of adding a new one if you first edit a row and then add one):

   1: private function saveData():void {

   2:    if (vOAuthor != null)

   3:       authors.saveData(vOAuthor);

   4: }

   1: <s:Button x="224" y="220" label="New" 

   2:     click="myForm.visible = true; vOAuthor = new VOAuthor()"/>

The final code of the MXML file should look like this:

   1: <?xml version="1.0" encoding="utf-8"?>

   2: <s:Application xmlns:fx="" xmlns:s="library://" xmlns:mx="library://" minWidth="1024" minHeight="768" xmlns:authors="services.authors.*">

   3:     <fx:Script>

   4:         <![CDATA[

   5:             import;

   6:             import services.authors.VOAuthor;

   7:             import;

   8:             import mx.controls.Alert;


  10:             protected function getData():void

  11:             {

  12:                 getDataResult.token = authors.getData();

  13:             }


  15:             private function dataEdited(event: DataGridEvent):void 

  16:             {

  17:                 vOAuthor = as VOAuthor;

  18:             }


  20:             private function saveData():void {

  21:                 if (vOAuthor != null)

  22:                     authors.saveData(vOAuthor);

  23:             }


  25:         ]]>

  26:     </fx:Script>

  27:     <fx:Binding destination="vOAuthor.fname_aut" source="fname.text"/>

  28:     <fx:Binding destination="vOAuthor.lname_aut" source="lname.text"/>

  29:     <fx:Declarations>

  30:         <s:CallResponder id="getDataResult"/>

  31:         <authors:Authors id="authors" destination="Authors" endpoint="http://localhost/flexPHPAMF-debug/gateway.php" 

  32:             fault="" 

  33:             showBusyCursor="true" source="Authors"/>

  34:         <authors:VOAuthor id="vOAuthor"/>

  35:     </fx:Declarations>

  36:     <mx:DataGrid x="44" y="37" id="dataGrid" dataProvider="{getDataResult.lastResult}" 

  37:         itemEditEnd="dataEdited(event)" editable="true">

  38:         <mx:columns>

  39:             <mx:DataGridColumn headerText="id_aut" dataField="id_aut"/>

  40:             <mx:DataGridColumn headerText="fname_aut" dataField="fname_aut"/>

  41:             <mx:DataGridColumn headerText="lname_aut" dataField="lname_aut"/>

  42:         </mx:columns>

  43:     </mx:DataGrid>

  44:     <s:Button x="43" y="220" label="Get Data" click="getData()"/>

  45:     <s:Button x="129" y="220" label="Save Data" click="saveData()"/>

  46:     <s:Button x="224" y="220" label="New" click="myForm.visible = true; vOAuthor = new VOAuthor()"/>


  48:     <mx:Form x="46" y="277" id="myForm" visible="false">

  49:         <mx:FormItem label="First Name:">

  50:             <mx:TextInput id="fname" text=""/>

  51:         </mx:FormItem>

  52:         <mx:FormItem label="Last Name:">

  53:             <mx:TextInput id="lname" text=""/>

  54:         </mx:FormItem>

  55:         <mx:FormItem>

  56:             <s:Button label="Add" click="authors.saveData(vOAuthor)"/>

  57:         </mx:FormItem>

  58:     </mx:Form>


  60: </s:Application>

The delete operation is left as homework for you! Basically you want to get the selected row, grab the object data used by that row and save it into vOAuthor, and then call the authors.deleteData(vOAuthor).


If you are not sure what remoting and the Zend Framework are, you can read my post that explains these matters: Flex and PHP: remoting with Zend AMF. This article uses Flex Builder 3 (the previous version of Flash Builder 4).

You might be wondering about many-to-many or one-to-many associations. Well, at least for now there is no support for PHP (at least there is no wizard that handles any association and generates all the code). Still, I think I could do it much easier using these wizards than without them. Having the glue code generated for me and the Value Object created automatically, being able to have a form generated for a particular data model are all great help. You save time, you save money. Remember with any line of code you write, you might introduce a bug or more. Having more lines generated for you means less bugs :).

If you want to take a look at my project, you can download it from here (you’ll find the PHP files and the dump of the database in the service folder from this archive). If you want to install Flash Builder 4, you can grab the beta version from here and use it.

Finally I encourage you to try this for yourself, and let me know what you think. If you find bugs or you want more features in Flash Builder 4, be sure you go to and ask your friends to vote for the bug. In the end, this is a beta product. If we can improve it, why not?

40 thoughts on “Working in Flash Builder 4 with Flex and PHP

  1. Thank you so much!!!! Huge… Huge… HUGEEEE help… monster step in the right direction… finally… after weeks of looking for something like this… its amazing how hard it is to find good info beyond how to dump a MySQL table into a Datagrid… (which is about the extent of help out there for php/Flex intergration)…

    Wanna be my Mentor? there’s no pay, but I’m willing to indenture myself lol… proofread code… I’m a monster in Photoshop… (yea, I know Designers shouldn’t code… lol).. .hell I’ll do the windows!! lmao

    seriously though, thanks so much for taking the time to write this… put me on the right track at least!

  2. Pingback: Flex 4 materijali | Ivan | Web i tome slično...

  3. Pingback: Data Paging with Flex and PHP in Flash Builder : Mihai CORLAN

  4. In the “Configure Operation Return Type” dialog, sometimes the existing data type will not show up in the “Use an existing action script or custom data type” combobox. You can select “Create New Custom Data Type” and type it there to work around this issue.

  5. Pingback: Diving into Flash Builder 4 - Mark Clemons

  6. Hey Mihai –

    Is a localized server environment, such as MAMP, required to setup the PHP data/service? I can’t for the life of me figure this out. All examples that I have found are using either MAMP or WAMP. What if you want to accomplish this on a production server?

    Thanks in advance for any insight.

  7. Hi Mihai ,
    Is it possible to create a tree with flex4 that data is given by a database?
    Can you help me please.

  8. Mihai,

    Great example; I have a question that I have not been able to figure out: your example as some others return all the records, how would one go about adding the code that would allow to return the records from a specific field where the data matched some user input from a text box?


  9. @Joel Sisko

    You mean like a search? It’s simple, you just have to create a search method in the PHP class, and then in Flex to add a textbox and a button in order to fill in the search criteria and start the search.

  10. I must be the most behind in understand. So I tried importing your flexPHPAMF.fxp into Flash Builder 4. However I don’t know how to configure the next screen “Update Path Variables”. Any assistance and further explanation would be most appreciated.

  11. @Essential1

    For the Web Root set the path to the PHP web server root (where the PHP files stay on your server).
    For the Root URL set the URL to reach the Web Root (usually this is http://localhost)
    For the Output folder location set the same path as the one for Web Root and add flexPHPAMF-debug.

    These should work.

  12. Thanks Mihai. Previously i prefer XML Data as datasource for my flex projects just because worrying php and mysql could be too though. But after read this post i decided to switch to php and mysql. Thanks a lot..

  13. I get the following error:

    1067: Implicit coercion of a value of type services.authors:VOAuthor to an unrelated type valueObjects:VOAuthor. flexPHPAMF.mxml flexPHPAMF/src line 25 Flex Problem

    this refers to:

    any ideas?

  14. Pingback: Data Paging with Flex and PHP in Flash Builder :: Flex Commando Adobe Flex Blog

  15. Hello,

    I actually had a problem with Flex 4 based ont his tutorial. I’ve been struggling with it for hours. In the editedData function I trace and the value is null. I assign VOObject = AS VOObject and trace(VOObject) and the value is null. I’m really stuck at this step and I’d like to get some sleep soon, please help!

  16. @Joel

    From what you are saying I understand that you don’t see any data on the client. If you’d see data then wouldn’t be null.

    So, the first step would be to fix any problem you have in order to see data (problems could be on the PHP side, like incorrect database credentials).

    After you see data, use the Flex debugger to see if the object has the type you expect. If the mapping from the PHP to ActionScript type is not correct, you’ll get instances of ProxyObjects and not VOObject.

  17. I see data on the client. The whole dataGrid is populated nicely.

    I have been tracing in the debugger since I see data and is returning null


  18. @Joel

    Once you see data in your data grid you should have a value for different than null.

  19. That would be really nice and make sense, but if that were true I wouldn’t be posting that it is returning null, would I?

  20. Nice example … however:
    1. FB beta 2 (windows 7) sucs: it works with eclipse 3.4 + plugin but complete installation NOT. Can somebody tell me why?

    2. Why implementation is only possible with wizard and zend framework? Is it not MUCH better to provide something like a DATA PROVIDER with parameters startIndex, maxElements, callbackFunction?

    my 5 cent


  21. hi

    this is my first flex application and i m trying to make a login form using wsdl. My wsdl return string called “Success” if the user name and password is correct.
    I call the web service at the click of submit button
    when i try to get the return value into a variable for eg:

    var info:String = service.lastResult

    i always get a null value at first. When i click for the second time, it returns the string.
    I m not able to understand. Please help.

    Thanks in advance,

  22. hi

    this is my first flex application and i m trying to make a login form using wsdl. My wsdl return string called “Success” if the user name and password is correct.
    I call the web service at the click of submit button
    when i try to get the return value into a variable for eg:

    var info:String = service.lastResult

    i always get a null value at first. When i click for the second time, it returns the string.
    I m not able to understand. Please help.

    Thanks in advance,

  23. great tut! Thanks a much! Answered a lot of my questions with your tut.

  24. i am looking to create a field in database by zend frame work can any one help me

  25. Great tutorial, really helped me understand Flash builder. I’m not a noob in AS3 and OOP so my background experience really helped. Thanks!

  26. For setting up a PHP-Flex project, you indicated: “Make sure that in the wizard you choose PHP as the server technology, and you give the correct information for the document root of the web server (absolute path and URL).”

    This only works for local WAMP/MAMP configuration. If I try to enter external server info (Web root and root URL), the configuration fails validation. For example, my external server web root absolute path is “D:\78963\www\mydomain\” and the root URL is “”.

    Any suggestions?

  27. I have the same problem than Kach, I want to connect to an external server and the web root fails validation…

  28. @Mihai Great tutorial and good job on the video as well.

    @Kash, Anna
    Hi, I dont know if you found the answer but I think you dont have access to your web root. In “my computer” the drive must be accessible, ie. you should be able to connect to D:\78963\www\mydomain\

    My servers are in linux enviroment so i set up samba and mount webroot as network drive for my dev server.
    So is simply z:\
    I am sure you can do a similar setup in windows servers.

  29. @Hob
    Thanks for the reply. My domain lives in a shared Windows server environment. There appears to be no way to map the remote web root(D:\78963\www\mydomain) to a local drive (z:\). I have yet to find a solution to my dilemma. Otherwise, I am forced to develop within a local WAMP setup.

  30. Hi Mihai, first I want to thank you for all this useful information, it’s been a great help for me.
    I use Data Services in my PHP-FLEX project a lot and i like automatic type recognition but I can’t find a solution for recognizing ByteArray(i have small pictures in my database to retrieve) types and it’s very annoying because every time I update the service class it’s assigning to it a new type something like Bytearray and not the existing ByteArray type in ActionScript and thus I’m forced every time on service update to correct the return type for the flex project to work. I searched a lot for a solution and finally with hope to find it left a comment here. Please Help. Thank You.

  31. Hi, Mihai:

    Your series of blogs are very helpful. One question: is Cairngorm framework able to fit into this picture smoothly? Theoretially Cairngorm is client side framework, it should be independent of what you discussed here, just want to see how it works practically, or should we use it with FlashBuilder4 at all?

  32. Hi,

    I got 2 questions on (Flash Builder 4.5 for PHP) autogenerated classes and authentication via AMF.

    1) As I understood, the authentication should be set up manually on the PHP side, for instance right in the gateway.php, just before the ‘handle’ call:

    // create server
    $server = new Zend_Amf_Server();

    // auth
    $authAdapter = new My_Custom_Auth_Adapter();

    // acl
    $acl = new Zend_Acl();

    // handle AMF request
    echo $server->handle();

    Now, I know about implementin initAcl($acl) method inside each service class, and it works fine.
    However, I’ve got the problem with auth. My_Custom_Auth_Adapter never gets called.
    I think it’s because at this state I’ve got no credentions sent from Flex through the wire (via headers).
    I expected that the methods shouldn’t be called if there are no credentials, but they somehow are.
    Now check this out:

    Server.php (Zend_Amf_Server) line 499:

    $handleAuth = false;
    if ($this->_auth) {
    $headers = $request->getAmfHeaders();
    if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) &&
    isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) {
    $handleAuth = true;

    … seems like the auth is handled only if there are credentials sent from Flex. Meaning that one can skip auth with no headers sent (?)

    2) now for the client. Do you know how am I supposed to supply the credentials to AMF call?
    Is it on each call?
    Or is it one per session?

    This is the best I know, but it doesn’t help:

    Thank you.


Leave a Reply