Flex and PHP: remoting with AMFPHP

Since I recently received some requests for a simple example on getting up to speed with Flex, PHP, and AMF, I decided to write a tutorial on this topic. I will show you how to do remote procedure calls from Flex to PHP classes using AMFPHP. Soon I will post an article on how to do RPC using the Zend Framework and ZendAMF.

What is AMFPHP and why should you use remoting?

If you already know these answers, you may want to skip to the next section.
Let’s start by understanding of remote procedure calls. Remote procedure calls let Flex applications  make direct calls on the methods of your server side classes. Using BlazeDS or LCDS 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 ZendAMF, WebOrb, and AMFPHP. This article focuses on remoting with AMFPHP, which uses a binary protocol (AMF) to serialize 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, James Ward has put together a nice benchmark.

AMFPHP is a PHP open source 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 said earlier, AMFPHP remoting uses AMF for serializing messages between the server and Flex client. And it offers a nice feature 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:

contacts
-------------------------------
id      primary key int
name    varchar(255)
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 model classes. This is what you need to do. And in Flex you will get an array of ActionScript objects. All the conversions from PHP to AMF format and from AMF format to ActionScript objects are done automatically for you by  Flex and AMFPHP.

When you use XML or JSON for remoting, usually you need extra steps in Flex to process the data in order to display or store it.

Let’s look at a working example.

Step 1: Install the AMFPHP and understand its structure

While it is not hard to create a Flex application that makes RPCs using AMFPHP, I found some possible glitches when you do it for the first time. If you missed something, you will end up with errors such as:

It is my intention to explain all the small things you need to take care of, so you can get it right.
First grab the AMFPHP library archive, unzip it somewhere on your machine and then copy the amfphp folder on your PHP webserver. From now on, I will refer to this folder as the installation folder. On my machine this folder is c:/htdocs/amfphp and the URL is http://localhost/amfphp.

If you open this folder you will notice a folder named “browser”. When you open this folder in your browser  (on my machine http://localhost/amfphp/browser) you will get a Flex application that lets you test all the exposed PHP classes:

AMFPHP: Browser service

Beside this folder, there is “services” folder. This is very important. In the “services” folder you need to place all the PHP classes you want to expose to Flex code. Also, all the PHP Value Object classes you want to use for modeling the data must be inside the folder “services/vo/” + <the package name as folders> For example if you have the ActionScript class org.corlan.VOAuthor and you want to map to a PHP class with the same name, then the PHP class should be in “services/vo/org/corlan/VOAuthor.php”.

These are the default configurations for AMFPHP. If you don’t like them you can open the globals.php file from inside of the installation folder and make changes.

Step 2: Create the PHP code

Let’s create a small PHP class that does two things:

  1. Reads and returns all the records from a table
  2. Offers a method to update one record

I use MySQL, and the table creation SQL is as follows:

CREATE TABLE `authors_aut` (
  `id_aut` int(11) NOT NULL auto_increment,
  `fname_aut` varchar(255) NOT NULL,
  `lname_aut` varchar(255) default NULL,
  PRIMARY KEY  (`id_aut`),
  UNIQUE KEY `fname_aut` (`fname_aut`,`lname_aut`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

--
-- Dumping data for table `authors_aut`
-- 

INSERT INTO `authors_aut` VALUES (1, 'Dantes', 'Alighierie');
INSERT INTO `authors_aut` VALUES (4, 'Niccolo', 'Machiavelli');
INSERT INTO `authors_aut` VALUES (3, 'Umberto', 'Eco');
INSERT INTO `authors_aut` VALUES (2, 'William', 'Shakespeare');

So I create a PHP file inside the amf/service/ folder called MyService.php. Inside of this file I create a PHP class with two methods: getData() and saveData(). The complete code is here:

<?php
require_once ('./vo/org/corlan/VOAuthor.php');

//conection info
define( "DATABASE_SERVER", "localhost");
define( "DATABASE_USERNAME", "mihai");
define( "DATABASE_PASSWORD", "mihai");
define( "DATABASE_NAME", "flex360");

class MyService {

    public function getData() {
        //connect to the database.
        $mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD);
        mysql_select_db(DATABASE_NAME);
        //retrieve all rows
        $query = "SELECT id_aut, fname_aut, lname_aut FROM authors_aut ORDER BY fname_aut";
        $result = mysql_query($query);

        $ret = array();
        while ($row = mysql_fetch_object($result)) {
            $tmp = new VOAuthor();
            $tmp->id_aut = $row->id_aut;
            $tmp->fname_aut = $row->fname_aut;
            $tmp->lname_aut = $row->lname_aut;
            $ret[] = $tmp;
        }
        mysql_free_result($result);
        return $ret;
    }

    public function saveData($author) {
        if ($author == NULL)
            return NULL;
        //connect to the database.
        $mysql = mysql_connect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD);
        mysql_select_db(DATABASE_NAME);
        //save changes
        $query = "UPDATE authors_aut SET fname_aut='".$author->fname_aut."', lname_aut='".$author->lname_aut."' WHERE id_aut=".  $author->id_aut;
        $result = mysql_query($query);
        return NULL;
    }
}
?>

The code is pretty simple. No abstract database layer, just the simplest PHP code to make something useful.

As you can see in the above code, I used the VOAuthor PHP class. So, now it’s time to create this class (this class models one row from the table). Basically this class will have one field for each row of the table (I will keep the name of the fields similar to the table fields) and an extra field that tells AMFPHP how to serialize the class when sending back the message. Let’s see the code and then I will explain a little more about this field:

<?php
class VOAuthor {

    public $id_aut;
    public $fname_aut;
    public $lname_aut;

    // explicit actionscript class
    var $_explicitType = "org.corlan.VOAuthor";
}
?>

The extra field is $_explicitType, and its value is the fully qualified ActionScript Value Object I intend to use in the Flex application to model the data. If you don’t configure this field correctly, then in the Flex app you will not get your strongly typed ActionScript class, but a dynamic object.

Important! Make sure you do not add empty spaces or other chars after the PHP closing tag. If you leave extra chars, the output buffer will be flushed and the message that AMFPHP sends to the Flex client will not be correctly formatted.

If you go back to the browser service of AMFPHP, you can try the code — select the getData method and click the Call button. You should get an array of objects.

Testing the service

Step 3: Create the Flex project

We have all the PHP code in place, it is time to create the Flex application. First step is to create a Flex project using the PHP server type (you can read here an article I wrote on how to create Flex and PHP projects if you want to find more tips and tricks). This is the first page of the wizard:

Creating the Flex project

Click “Next” and then “Finish”.

Step 4: Create the ActionScript code

Now let’s create the ActionScript value object class, VOAuthor. Right click on the “src” folder and choose New > ActionScript class (make sure you enter the package name):

amfphp_4

The code for this class is:

package org.corlan {

    [RemoteClass(alias="org.corlan.VOAuthor")]
    [Bindable]
    public class VOAuthor {

        public var id_aut:int;
        public var fname_aut:String;
        public var lname_aut:String;
    }
}

How does Flex know to serialize the ActionScript VOAuthor class to the PHP VOAuthor? Because of the tag RemoteClass. Here you enter the name of the PHP class you want to use and the path from the “amfphp/vo/” to the class as the package name. Thus I end up with “org.corlan.VOAuthor”.

It is time to put all these together and create the ActionScript code that makes the call to the PHP class and displays the info. For this, open the php_amf.mxlm file if it isn’t already open and add this code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Script>
        <![CDATA[
            import mx.controls.dataGridClasses.DataGridColumn;
            import mx.events.DataGridEvent;
            import org.corlan.VOAuthor;
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.collections.ArrayCollection;

            /**
             * This function is called when an item was edited in the data grid.
             * Calls the saveData() method on the PHP server 
             */
            private function save(event :D ataGridEvent):void {
                var dataGrid:DataGrid = event.target as DataGrid;
                var dsColumnIndex:Number = event.columnIndex;
                var col:DataGridColumn = dataGrid.columns[dsColumnIndex];
                var newValue:String = dataGrid.itemEditorInstance[col.editorDataField];
                var dsFieldName:String = event.dataField;
                var author:VOAuthor = event.itemRenderer.data as VOAuthor;
                if (newValue == author[dsFieldName])
                    return;
                //get the new value for the first name or last name
                author[dsFieldName] = newValue;
                myRemote.saveData(author);
            }
        ]]>
    </mx:Script>
    <!-- this is the RemoteObject  used to make the RPC calls -->
    <mx:RemoteObject id="myRemote" destination="MyService" source="MyService"
            endpoint="http://localhost/amfphp/gateway.php" showBusyCursor="true"/>

    <mx:VBox top="30" left="100">
        <mx:Button label="Get data" click="{myRemote.getData()}" />
        <mx:DataGrid id="myGrid" dataProvider="{myRemote.getData.lastResult}" editable="true" itemEditEnd="save(event)">
            <mx:columns>
                <mx:DataGridColumn dataField="id_aut" editable="false"/>
                <mx:DataGridColumn dataField="fname_aut"/>
                <mx:DataGridColumn dataField="lname_aut"/>
            </mx:columns>
        </mx:DataGrid>
    </mx:VBox>
</mx:Application>

For remoting, Flex uses RemoteObject. As you can see in my code, I create one instance of this object. Then I configure the endpoint to work with AMFPHP and the PHP class (MyService). For this I add the URL to the gateway.php file as the value of the attribute endpoint, and I set MyService as the value of the destination and source attributes.

The UI of the application is very simple: a button to call the getData() method from the server and a data grid for displaying and editing the data. The binding between the data retrieved from the server and the data grid is done directly on the data grid using the property lastResult: dataProvider=”{myRemote.getData.lastResult}”.

There is an event listener registered on the data grid for the event of ending the editing of a cell. Inside this event listener, I call the saveData() method using the instance of the currently edited Value Object.

Final words

That’s it folks! If you are too lazy to set up the project and copy and the code, you can download the project from here. Read the readme.txt after you import the project in Flex Builder using the Import wizard > Flex Builder. I will post another article on ZendAMF soon. See you!

Comments

74 Responses to “Flex and PHP: remoting with AMFPHP”

  1. avidFlex on October 22nd, 2008 10:22 am

    Hi there,

    Been referring to what u posted abt AMFPHP and Flex and must say its really comprehensive. Just a question though, I keep getting AMF message errors in the localhost AMFPHP browser and this causes my application to unexpectedly quit during runtime. What i’m trying to do is create a simple flex form which links to AMFPHP and inserts the data into the database.

    Any suggestions?

    Thanks
    avidFlex

  2. Mihai Corlan on October 23rd, 2008 12:05 pm

    Hi there!

    What I would do:
    1. Make sure that there are no errors in the PHP class you want to call from Flex. Just open the scrip in a web browser and see if there are errors (you should have PHP configured to output the errors)
    2. Make sure there are no spaces or enters before the opening and after the closing tag < ?php / ?>
    3. Next I would try to reach the method using AMFPHP browser. Alternatively, you can add a small code at the top of the PHP class, to instantiate the class and call the method you want with the given arguments. This way you check that the PHP code is working correctly
    4. Finally, if all the steps before were passed, you probably have something wrong on the Flex side. Either you didn’t configure correctly the RemoteObject,or the VOs or something.

    While working with AMFPHP is not rocket science, it needs a lot of attention for details, and when you try for the first time it can be a little difficult.

    Good luck!

  3. Gilly on October 24th, 2008 12:13 am

    Thank you very much for this tutorial.. (Indeed one get quickly lost although it looks simple..)

    In your RemoteObject definition you define destination=”MyService” source=”MyService”
    I suppose the source is the actual php file in amfphp\services, but what should be the destination ? I thought it was the identifier of a destination defined in a config-file but I don’t see it in your services-config.xml …
    Thanks,
    G.

  4. Mihai Corlan on October 24th, 2008 9:15 am

    Hi Gilly,

    Both destination and source for AMFPHP need to be the name of the PHP class if you want not to use the remote-config.xml file. So, this is why you don’t need this configuration file.

    cheers

  5. Marty on November 6th, 2008 4:37 pm

    Thanks Mihai!

    I’d been banging my head against the keyboard trying to get AMFPHP to return my objects, until I ran across your article. No other tutorial seemed to mention that you needed to place them in services/vo/.

    Keep up the good work!

    Cheers!

  6. Flex and PHP: remoting with Zend AMF : Mihai CORLAN [http://corlan.org/2008/11/13/flex-and-php-remoting-with-zend-amf/] on November 13th, 2008 6:58 pm

    [...] way to get your data in Flex/AIR clients, I wanted to add a short post explaining how to do use it (here is another post I wrote on remoting with AMFPHP). Actually this post, is a part of a larger article [...]

  7. Jean-Claude on November 24th, 2008 2:10 am

    {myRemote.getData.lastResult}??

    Would you please elaborate more on the use of the above code, I searched the datagrid methods and I did not see anything related to getData.lastResult

    myRemote calls getData.lastResult which is located where? it was not in the php code or the actionScript code. WHere is it?

  8. Mihai Corlan on November 24th, 2008 12:40 pm

    @Jean-Claude

    On any RemoteObject, there is a property for each method, that offers access to the last result from the server. In my example I have the method getData() defined on the PHP class. Thus when I call this method in Flex, I have the property on the RemoteObject “getData”, and on this property I have the property lastResult.

    This is not a property of the data grid, but of the RemoteObject. You can find more looking in the Flex documentation.

  9. Munich Flex and PHP user group meeting : Mihai CORLAN [http://corlan.org/2008/12/09/munich-flex-and-php-user-group-meeting/] on December 9th, 2008 2:31 pm
  10. Chaz [http://www.modernlighting.com/] on December 18th, 2008 7:28 pm

    Can I run flex swf file on a coldfusion server making a remote call to a php class?

    Thanks
    Chaz

  11. Mihai Corlan on December 19th, 2008 12:28 pm

    @Chaz
    Yes you can. Probably you will do a call to another domain name than the one that served the SWF file. If this is the case you have to either have cross-domain policy file on the PHP server, or to use BlazeDS and proxy features, that lets you make call to other domains without the need of cross domain file.

  12. Chaz [http://www.modernlighting.com/] on December 19th, 2008 9:35 pm

    Thanks for getting back quickly…

    Is this just for flex 3 or can I use this example for flex 2?

    Thanks
    Chaz

  13. Mihai Corlan on December 19th, 2008 11:53 pm

    @Chaz

    Should work with Flex 2.0.1 Hotfix 3. Let me know if it doesn’t.

  14. Chaz [http://www.modernlighting.com/] on December 22nd, 2008 9:14 pm

    thanks a lot it works with Flex 2.0.1, i do not know which Hoxfix i have.

    Thanks

  15. jcarlos on January 1st, 2009 5:11 pm

    Thank you very much for this great and clear tutorial.

    If you have any example, link or direction showing how to have user authentication with remote object calls I would thank you a lot.

    I´m still a newbie with flex and having a hard time to find even small but complete examples where the user is authenticated (I find one of yours, great too!) and after that how to send the the user´s credentials, or session, or token to validate the data access.

  16. Mihai Corlan on January 2nd, 2009 12:54 am

    @jcarlos

    You can have a look to my post here: http://corlan.org/2008/07/22/flex-air-php-and-user-authentication/

    Thank you for the nice words!

  17. Throwing an error when working with PHP and AMF : Mihai CORLAN [http://corlan.org/2009/01/07/throwing-an-error-when-working-with-php-and-amf/] on January 7th, 2009 10:37 pm

    [...] As a starting point you can have a look at the two articles I wrote on PHP and AMF ZendAMF and AMFPHP. You can use the projects that you find attached [...]

  18. Raymond [http://www.fouleemuroise.fr] on January 10th, 2009 4:09 pm

    Hi,
    Thanks for that great tutorial, it’s just what I required to understand how to easily connect to my mysql DB

  19. jcarlos on January 20th, 2009 2:04 am

    Hi Corlan,

    I´m trying to test the function saveData($author) in the MyService.php with the amfphp browser. I wasn´t getting to solve that in the tests I´ve been doing so I decided to go back to your first example.

    I want to test the services with the browser before going to Flex.

    I´ve tried several recommendations and none of them worked at all.

    The last one was the string below

    {“id_aut”:4, “fname_aut”:”maria”,”lname_aut”:”joao”}

    What is the right way to have a VO as a parameter in the amfphp browser to test the services?

    Thanks again

  20. Nuwan on January 24th, 2009 7:50 pm

    This was really helped for me.
    Thank you very much for nice post.
    Keep up good work!

    Thanks.

  21. luigi on February 13th, 2009 6:39 am

    hello Mihai! i have try to implement this tutorial in my code but i can´t populate my datagrid. o don´t care for now the save method. the getData method work fine in the afm browser. but i see only the bussy cursor for a while in mi app and then nothing. sorry about my english. i know its poor! haha.
    where can be my problem? any suggestion?=’

  22. Mihai Corlan on February 13th, 2009 12:06 pm

    @luigi

    Please look at the previous comments. Most likely you have an error in the save method. Try to execute the save method from PHP script and see what is the output. Good luck!

  23. luigi on February 13th, 2009 3:39 pm

    Mihai

    thanks for your answer! i well try!

  24. Flex and PHP: remoting with WebORB : Mihai CORLAN [http://corlan.org/2009/02/18/flex-and-php-remoting-with-weborb/] on February 18th, 2009 3:18 pm

    [...] this stage), AMFPHP, WebORB for PHP, and SabreAMF. I’ve already written articles on two of them, AMFPHP and ZendAMF. On this post I will focus on WebORB. Next, I will play with SabreAMF, and I will [...]

  25. Paul on February 19th, 2009 5:34 pm

    Thaks Mihai!
    Your article helped me great. But …

    I recieve all data from PHP correctly dataGrid arranges correctly and rendering passes too. But the focus on the items I click is wrong, it is even stay on one and the same item.

    Intresting the thing that .. SelectedItem parameter shows correct Indices and returns correct data on SelectedItem.something … don’t know what to do …

    And one more thing …. how can I addEventListener to a method that is in myService????? Bec. I faced that thing that I can’t adequately parse the result by myRemote.getMessage.lastResult … for the 1st time I get nothing and for the 2nd i recieve that should be in the 1st time.

    Thanks.

  26. Paul on February 19th, 2009 5:36 pm

    myRemote.myMethod.addeventListener(……..) doesn’t works

    myMethod is a PHP class method.

  27. Paul on February 19th, 2009 5:42 pm

    I made it such a way

    itemClick=”myRemote.getMessage(messageGrid.selectedItem.mid, messageGrid.selectedItem.timestamp); myRemote.addEventListener(ResultEvent.RESULT, function result():void {Alert.show(myRemote.getMessage.lastResult); myRemote.removeEventListener(ResultEvent.RESULT, result)})”

  28. Paul on February 19th, 2009 5:45 pm

    I made it such a way

    itemClick=”
    myRemote.getMessage(messageGrid.selectedItem.mid, messageGrid.selectedItem.timestamp);

    myRemote.addEventListener(ResultEvent.RESULT, function result():void {Alert.show(myRemote.getMessage.lastResult);

    myRemote.removeEventListener(ResultEvent.RESULT, result)})”

    it works normally … but you need to set eventListeners every time you calling different methods …. it is not comfortable … may be there is another way to solve it ???

  29. Dan on February 24th, 2009 10:34 pm

    Hi Mihai,

    I have a PHP download script for files that allows files to be stored below the web accessible public_html folder so that no one can directly link to the file, but only download it from my app.

    With Flex, however, the FileReference does not allow this…files have to be browser accessible.

    Would AMFPHP allow me to utilize my PHP script for pushing the download to the user from Flex?

    Using HTTPSERVICE and the PHP file doesn’t work as I had assumed.

    Any advice and thoughts would be great.

    Thanks,
    Dan

  30. Noel on February 27th, 2009 10:14 pm

    Hi Mihai

    The updated values from the grid are not being reflected in the mysql table

  31. Noel on February 27th, 2009 10:37 pm

    Hi

    i am getting an associative array in php for the saveData part…so the -> operator gives a null value but i can access the values with associative array syntax…what could be my error?

  32. Meito Lolelo on March 7th, 2009 9:39 pm

    Hi, i am kind of new at flex with php, i follow your instructions but i get this error, thanks

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at RawAmfService/readData()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at flash.net::URLLoader/onComplete()

    Thanks for your work is very good, hope i can finish the tutorial

  33. Flex and PHP: remoting with SabreAMF : Mihai CORLAN [http://corlan.org/2009/03/26/flex-and-php-remoting-with-sabreamf/] on March 26th, 2009 9:43 pm

    [...] the past months I wrote a lot on Flex and PHP remoting using AMFPHP, ZendAMF, and WebORB. However, there is another library, SabreAMF, that can be used to do remoting. [...]

  34. Flex and remoting with PHP, which library is the best: Zend AMF, AMFPHP, WebORB for PHP, or SabreAMF? : Mihai CORLAN [http://corlan.org/2009/03/31/flex-and-remoting-with-php-which-library-is-the-best-zend-amf-amfphp-weborb-for-php-or-sabreamf/] on March 31st, 2009 6:09 pm

    [...] your PHP server, and you’re wondering which of these four libraries is the best: Zend AMF, AMFPHP, WebORB for PHP, and [...]

  35. Jacob [http://-] on April 5th, 2009 3:58 pm

    Hi there,

    I see you use the remoteobject.getdata.lastresult as dataprovider for the datagrid.

    what i would like to do is call a function getdata when you push the button. that function gets the data from the server, creates an arraycollection of VOAuthor objects and returns that as dataprovider to the datagrid.

    This way i can create my own component and use the arraycollection i filled locally.

    Please some help here,

    Greets, Jacob

  36. Jacob [http://-] on April 5th, 2009 5:55 pm

    Hi,
    I figured out the answer to my question;
    ——————————————-
    private function getdatafromserver():void{
    myRemote.getData();
    }
    private function dataEventHandler(event:ResultEvent):void{
    // populate data into variable myarray
    var myarray:Array;
    myarray=event.result as Array;
    trace(myarray);
    // populate data into myGrid datagrid.
    myGrid.dataProvider= myarray;
    }
    ]]>

    ————————————-
    This way you have the data in an array and you can use it for your custom component.

    Greets, Jacob

  37. Jacob [http://-] on April 5th, 2009 6:01 pm

    again a message from me,
    there where a loss of code during my prev post.

    you need to put result=”dataEventHandler(event)” inside the remoteobject tags and remove the dataprovider.

    Now you can let the button call the getdatafromserver function by using; click=”{getdatafromserver()}”

  38. Mihai Corlan on April 6th, 2009 10:08 am

    @Jacob

    It’s very simple:
    1. register a listener for result event on the remoteobject;
    2. Create the listener function and do something like this: myArrayColl = new ArrayCollection(event.result as Array);

  39. Josh on April 10th, 2009 12:36 am

    Maybe a stupid question here, but I’m new to this type of architecture. Why are you creating VO on both the server side as well as client side? Seems like extra work when you could just create VOs on the Flex/Flash/ side and send back SQLResults from PHP and send VOs to php methods that did your sql updates, deletes, inserts, etc.

  40. Mihai Corlan on April 10th, 2009 10:34 am

    @Josh

    If I had VOs only on the Flex side, then all the data send from PHP will be only proxy objects (not my ActionScript VOs). And in the PHP side, I would work with associative arrays instead of typed objects.

    For me, there is a big value in being able to work with typed objects (compile time error checking, code hinting tool support)

  41. Josh on April 10th, 2009 6:13 pm

    Hmm. I see your point, but you are going to have to convert from SQLResult to VO somewhere, why not do it client side (in the proxy) and spare the server the extra work. Also, can’t you just type everything on the Flex side so you know that you are putting in correctly typed info before you go to SQL? I hope this doesn’t sound like I’m trying to prove some point that way x is better than y. I’m just trying to understand the methodology behind this stuff.

  42. Carlos on April 19th, 2009 8:47 pm

    Hi, Mihae….We are waiting ansiously your answer about: AMFPHP,WEBORB,sabreAMF and zendAMF. ready?

  43. Mihai Corlan on April 19th, 2009 11:13 pm

    @Carlos

    I can’t wait too. See you soon :)

  44. phil on May 7th, 2009 6:02 pm

    Hi,

    it works fine but it’s impossible to save the data, if I use Charles, he gives “UPDATE authors_aut SET fname_aut=”, lname_aut=” WHERE id_aut=”

    and if I look to the authors’s content receive by Charles, he says :
    lname_aut | string | shakespare
    id_aut | integer| 2
    fname_aut| string | toto

    _explicitType | string | org.corlan.VOAuthor

    What’s the problem ?
    Thanks
    phil

  45. Jacob [http://-] on May 11th, 2009 3:28 pm

    is it possible to send a zip file from flex to amfphp using the remoteobject?

    The thing i would like to do is.. in flex i have multiple records in a sqlite db.
    - get all data of one record..
    - get the 2 images that belong to that record
    - create textfile for record text.
    - save images and textfile in a zip
    - send it to server.
    - unpack zip
    - store images
    - read textfile
    - store data from text file in mysql db.
    - send a complete back to flex so i know its done and i can send the next record.

    Or would there be a better solution to send data and images to flex.. and store all.
    Sending the images as binarydata or something?

    greets, jacob

  46. Richard on May 16th, 2009 2:48 am

    Hi Mihai

    I really enjoyed your tutorial. I’m working on my first Flex project and tried installing it. I have the AMFPHP folder in my desktop web application. How do I define the web points for my application? During development I use the http://localhost/amfphp/gateway.php endpoint. The client when they install there application won’t have a local host set up. Is there a work around for this. My project contains everything. I can connecgt to a remote web service but not the local one.

    I tried using this

    Any suggestions. I’m sure that this is a common problem. Thanks

  47. Mihai Corlan on May 17th, 2009 1:04 pm

    @Richard

    You can configure the RemoteObject at runtime. For example you could put all the configuration you need (like endpoint for example) in a text or XML file on your server, in the same folder as the Flex application. Then, when the application is loaded you use a HTTPService to load the XML file, get the value for the Endpoint and create the remoteObject.

  48. Richard on May 17th, 2009 3:52 pm

    Hi Mihai

    Thanks for your help. I’m still a little confused how Flex works. The client won’t have a local host. I’m using sqlite3 which will be installed along with there application and amfphp.Does the end point have to be a valid uri? How does amfphp communicate locally without a localhost? On my development computer I have a local host where the amfphp directory resides along with the web service files. For deployment purpose I copied everything over to my flex application folder which I have the amfphp directory and the sqlite3 database embeded in my application. How do I use the endpoints when the user doesn’t have a localhost installed?

    I see how my remote web service works. I simply call the uri for my web service and it call the amfphp file on my web server. But running locally when the entire application contains everything I’m scratching my head. I can go back and change all my queries to by pass amfphp but that is not an elegant solution.

    I guess what I’m trying to say how does Flex communicate on a desktop application without a localhost installed? I see all the great examples that you provide and others. But when it comes to deploy a desktop application using Flex with this configuration I’m missing something. I know the answer lies with the endpoints.

    Thanks for responding. From your examples it has helped me tremendously.

  49. Mihai Corlan on May 18th, 2009 9:51 am

    @Richard

    All the server code must goes to the server. AMFPHP is a server side library. Thus this library will go to your server as well. And the gatewat URL will be something like http://yourserverdomain.com/amfphp/gateway.php for example.

    Just to recap:
    - AMFPHP goes to your server;
    - the endpoints must be updated to reflect that new URL;

  50. Richard on May 18th, 2009 5:08 pm

    Mihai

    Thanks for clarifing things.

    Richard

  51. Thomas on May 26th, 2009 12:04 pm

    Hi ,

    Could you mind let me know how to update to mysql db if the editable=”true” ? Many Many Thanks!

  52. Mihai Corlan on May 26th, 2009 11:06 pm

    @Thomas

    It is in my article! Actually you can rewrite the listener for itemEditEnd event thrown by the datagrid like this:

    itemToBeSaved = event.itemRender.data as VOAuthor;

    and then call the saveData method on the RPC:
    myRPC.saveData(itemToBeSaved);

  53. Thomas on May 27th, 2009 8:24 pm

    Hi, Thank you for your help, but I still can not update to mysql database after set temToBeSaved = event.itemRender.data as VOAuthor; and myRPC.saveData(itemToBeSaved); , could you mind let me konow how to debug in this part ? another question, if I have retirve the data is the file name abc.jpg in datagrid column, can I change to display the actual picture instead of the file name abc.jpg in datagrid ? Many many Thanks!

  54. Mihai Corlan on May 28th, 2009 9:33 am

    @Thomas

    You can use Zend and Flex debugger. Find an interesting article here: http://miti.pricope.com/2008/06/06/debugging-flex-and-php-with-flex-builder-and-zend-studio/

    yes you can, you have to understand how item renderes are working, and you can use an image tag maybe.

  55. Thomas on May 28th, 2009 9:39 pm

    Hi,

    I have fixed the problems. Thank you for your help!

    Best Regards,
    Thomas

  56. Thomas on May 29th, 2009 8:46 pm

    Hi,

    Could you mind teach me how to filtering in DataGridColumn ? Many many thanks!

    Best Regards,
    Thomas

  57. handoyo on July 10th, 2009 8:20 am

    Hi,thanks for the tutor here..I’m intending to create an online store..Can you help meby pointing me which one should i choose between zendamf with amfphp?Thanks..

  58. Mihai Corlan on July 10th, 2009 11:05 am
  59. handoyo on July 10th, 2009 11:27 am

    @Mihai Corlan Ok,Thanks…

  60. cyianite [http://www.supercyian.com] on August 31st, 2009 1:41 pm

    hi there,
    I don’t get why do we need AMFPHP for remoting?, its seems its just doing the same way how you remote a service via httpService , but the only difference is AMFPHP has gui a to your browser. Can you please explain me more, maybe I’ll be more delighted with your explanation?. Sorry for my ignorance :)

    Cyianite

  61. Mihai Corlan on August 31st, 2009 5:14 pm

    @cyanite

    I think the first section of my article explains the differences between remoting and REST style services (with httpService). On short you get better performance with remoting, and the code is much easier to maintain/debug.

  62. Cyianite on September 9th, 2009 7:11 am

    Thanks pal. Nice posting and keep it up

  63. shrihari [http://www.aakstech.com] on September 29th, 2009 5:25 pm

    Hello,
    I am using amf to connect php to flex.I am able to do with local server but facing problem with the global server please help me.

  64. thodoris on October 27th, 2009 9:49 pm

    I have used succesfully zend amf communication through php and flex but i need to put the mysql connect username and passwords in every function i create.
    It seems that the flex don’t create an actual object of my php class becouse i cant access class variables like $foo.
    Using something like remoteObject will help?
    I am using flash builder 4beta2.
    thanks for any hint or suggestion.

    <?php
    class RoomTypesController {
    $foo;
    function f1(){}
    function f2(){}

    }

  65. Matthew [http://NA] on November 3rd, 2009 5:44 am

    Hi, I liked your post… I was wondering if it is a requirement of AMFPHP in that your VO objects have to have public fields. Can your fields not be private? I noticed when i have my VO with private fields the browser utility that comes with amfphp doesn’t show my object having any fields..

    I assume public fields are a requirement from whatever introspection technique amfphp uses.

  66. Shreyas on November 10th, 2009 11:46 am

    Hi Mihai,

    This is a very good article on Flex and AMFPHP.

    What I wanted to ask is- What is the use of the destination property for the RemoteObject? Why does it need to be assigned when we are not using a services-config.xml here?

  67. Stephen [http://www.jetboxdigital.com] on November 18th, 2009 12:16 pm

    Nice article Mihai!

    For anyone interested in seeing an example using Cairngorm and SabreAMF read this article:

    http://www.jetboxdigital.com/2009/11/flex-recordsetgrid-example/

  68. Shankar on December 4th, 2009 9:15 pm

    Hi,

    I created an application using Flex3,AMFPHP,PHP and MySql and i hosted the site, but i cannot get connected to the database through the amfphp. i checked in the service browser and the gateway.php path was correct. so what can be the problem. Please help me.
    Thanks.

  69. davet on January 22nd, 2010 12:42 pm

    Hi

    Great tutorial which made my first steps into AMFPHP really straightforward. Many thanks for you help

  70. ariel sommeria [http://arielsommeria.com/blog] on February 5th, 2010 7:13 pm

    Hi Mihai,
    just to let you know, we made a new release to AMFPHP. 1.9 is out, and we have some things going for 2.0
    bye
    Ariel

  71. Fodder on February 8th, 2010 6:05 am

    OK, using an event to pass the data back to an array:

    eg:
    public function onServiceResult(e:ResultEvent):void
    {
    myArray = new Array(e.result as Array);
    }
    all good, but curiouse to know why the results appear as the first element of a nested array in myArray

    so to access the first result (lets call it id), I have to use

    myArray[0][0].id rather than myArray[0].id
    how do i remove this?

    thanks, (new to flash/flex)

  72. Fodder on February 8th, 2010 6:25 am

    solution nis to remove the new, to populate the existing array as as it stands.

  73. Olga on February 8th, 2010 12:17 pm

    I’m using Apache 2.0.54 and PHP 5.0

  74. Olga on February 8th, 2010 4:49 pm

    Hello,
    When I go to
    http://localhost/amfphp/browser/

    the error message appears: (mx.rpc::Fault)#0
    errorID = 0
    faultCode = “Client.Error.MessageSend”
    faultDetail = “Channel.Connect.Failed error NetConnection.Call.BadVersion: ”
    faultString = “Send failed”
    message = “faultCode:Client.Error.MessageSend faultString:’Send failed’ faultDetail:’Channel.Connect.Failed error NetConnection.Call.BadVersion: ‘”
    name = “Error”
    rootCause = (Object)#1
    code = “NetConnection.Call.BadVersion”
    description = “”
    details = “”
    level = “error”

    Can you help me,please?

Leave a Reply