Hacking the AMFPHP Deserializer with Propel

AMFPHP, PHP No Comments »

I've been working on a project lately that uses Flex, AMFPHP, Propel and MySQL. For most of you these technologies may be well known, except maybe for Propel. In this post, I'll briefly mention what Propel is, what it does and how you can hack the AMFPHP Deserializer to make maximum use of Propel.

Propel

From the Propel project website: Propel is an Object Relational Mapping (ORM) framework for PHP5. It allows you to access your database using a set of objects, providing a simple API for storing and retrieving data.

Propel allows you, the web application developer, to work with databases in the same way you work with other classes and objects in PHP.

* You don't have to worry about database connections or writing SQL -- unless you want to.
* You never have to worry about escaping data or type-casting results.
* You define your database in a simple XML format (or tell Propel to build it from an existing database) and Propel will create database initialization files for your database and will generate static classes and objects that provide an OO interface to your database. (It can generate other useful things based on the datamodel too!)
* Propel builds classes which are aware of the structure of your database so there's no performance lost to initialization or to on-the-fly database metadata queries.

Most of you will agree that writing database queries and access code is one of the most tedious jobs in application development. Propel does an extremely good job at simplifying this work for the reasons mentioned above.

Mapping objects

The classes built by Propel use explicit getters and setters. That means they have methods like "setMyProperty" and "getMyProperty" to modify and access their fields. In addition to that, collections are an exception to that rule because they don't define a setter method. Instead, they define a method like "addMyItem" to fill the collection called "myItems".

The setter methods don't just set a property. They also contain logic that will mark a property as modified so that queries can be optimized.

The first step in setting up automatic mapping of the client and server objects, is to create Data Transfer Objects (DTO's, also known as Value Objects or VO's - although I prefer DTO after reading Eric Evans' DDD book.) that have the same property names as the protected properties in the PHP classes generated by Propel. To simplify the server objects, we changed the protected scope to public since it then allows us to send these to the client.

So what we have so far is a bunch of classes on the server and a bunch of classes on the client. Sending an object from server to client will allow mapping at this moment since we changed the protected scope of the properties to a public scope. Also note that you need to instruct AMFPHP about the type of the class by defining it in every object you want to map:

PHP:
  1. class MyClass extends BaseMyClass{
  2.   var $_explicitType="MyClass";
  3. }

Mapping objects from client to server

Mapping objects from client to server is actually not that easy. After all, when we send a property from the client, say "myProperty", the AMFDeserializer inside AMFPHP will try to set a property called "myProperty" on the mapped server object. This would actually work, but the queries would fail to execute correctly since they will not see any properties as being modified. That's why we need to call the setter method "setMyProperty" instead, which will mark the property as modified.

In order to invoke the setters (and "add*" methods of the collections) we changed the AMFDeserializer class so it tries to invoke setters dynamically. Let's jump right into the code.

PHP:
  1. // method "readAmf3Object"
  2.  
  3. for ($i = 0; $i <$memberCount; $i++)
  4. {
  5.   $val = $this->readAmf3Data();
  6.   $key = $members[$i];
  7.  
  8.   if ($isObject)
  9.   {
  10.     $isCollection = (substr($key,0,4) == "coll");
  11.    
  12.     if ($isCollection)
  13.     {
  14.       $addMethod = "add" . substr($key,4,-1);
  15.      
  16.       foreach ($val as $item)
  17.       {
  18.         $obj->$addMethod($item);
  19.       }
  20.     }
  21.     else
  22.     {
  23.       if ($key == "isNew")
  24.       {     
  25.         $setter = "setNew";
  26.       }
  27.       else
  28.       {
  29.         $keyparts = explode("_", $key);
  30.         $setter = "set";   
  31.        
  32.         for ($j=0; $j<count($keyparts); $j++)
  33.         {
  34.           $setter .= ucfirst($keyparts[$j]);
  35.         }
  36.       }
  37.                        
  38.       if (method_exists($obj, $setter))
  39.       {
  40.         $obj->$setter($val);
  41.       }
  42.       else
  43.       {
  44.         $obj->$key = $val;
  45.       }
  46.     }
  47.   }
  48.   else
  49.   {
  50.     $obj[$key] = $val;
  51.   }
  52. }

The above code tries to match the name of the setters by looking at the name of the properties inside the object being send. If it finds a setter method, it will invoke it and pass in the property as a value. The code will also try to detect a collection and invoke the "add*" method instead of a setter. There's also a "isNew" property to instruct the classes whether to do an update or an insert query when the save method is invoked on an object.

This hack brought me to the idea that AMFPHP should maybe provide a pluggable architecture for the serializers and deserializers. Instead of going into the code and modifying it to suit your needs, you could then register a custom (de)serializer in the config which will be used. Upgrading to newer versions of AMFPHP would then be less of a pain.

Anyway, hope you find this useful. Have fun coding!


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

www.amf-php.org

AMFPHP No Comments »

Update your bookmarks and links, the new amfphp site can be found at www.amf-php.org


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

MMUG Flash Remoting session files

AMFPHP, Flash, PHP 2 Comments »

A quick post to let you know that the Flash Remoting presentation files from last thursday at the MMUG Belgium are online. I covered Flash Remoting with AMFPHP and shared some project experiences, tips and tricks and showed a bunch of examples.

You can get the files here. The zip file includes the presentation slides, all the examples, the database dumps and the AMFPHP classes.

Many thanks to MMUG Belgium (Serge and Peter) and MultimediaCollege for the venue.


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

Flash Remoting components for Flash 8, AS2.0 available now

AMFPHP, Flash 1 Comment »

Macromedia has released an updated version of the Flash Remoting components.

September 20, 2005
This version of the Flash Remoting components supports Flash Professional 8 and Flash Basic 8. It is currently available in English; French, German, and Japanese versions will be available shortly. The English version can also be installed with other language versions of Flash.

The installer available includes:

  • Flash Remoting Component
  • Support files for Flash 8
  • NetConnection Debugger
  • HTML content that can be viewed within the Help panel in Flash
  • ActionScript 2.0 API class source code

Download page: here
Release notes: here

Direct Windows installer link: here

Through RocketBoots


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

ServiceCapture

AMFPHP, Flash 1 Comment »

Just in case you missed the news, ServiceCapture is a great tool for debugging Flash Remoting applications.

What is it?

ServiceCapture runs on your pc and captures all HTTP traffic sent from your browser or IDE. It is designed to help Rich Internet Application(RIA) developers in the debugging, analysis, and testing of their applications.

ServiceCapture is the only tool of its kind to deserialize and display all Flash Remoting or AMF traffic in a simple-to-use interface.

ServiceCapture also has a unique bandwidth simulation feature. This allows engineers to throttle their bandwidth to simulate dial-up, dsl, and cable connection speeds, even when your entire application is being served locally.

I've been using it over the last week and really enjoy it. I personally replaced it with Charles HTTP debugger. It does not have that many features (yet?) as Charles, but the Remoting support is what I needed the most so...enjoy!


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 
WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Login