Zend_Amf and Flash Remoting – Some things to note

Leave a comment

Having done a little bit of work with Flash over the past several weeks there are a couple of things I've discovered as I've worked through some practical examples.  There's only really one thing signficant, but a couple of things that you need to be aware of when doing Flash remoting with Zend Framework.

Simple interface? Easy. Useful interface? Just a little harder.

In other words, with a simple architecture it's easy to do.  In a more useful architecture there are some things to be aware of.

When dealing with POPOs (Plain Old PHP Object) remoting is stupid simple.  What a POPO is is a PHP object that simply defines its properties as public and doesn't have much integration with the surrounding application. However, when you start trying to integrate within a larger framework, application or module (such as Zend_Db) then it gets a little more difficult.  Not horribly difficult, but you might need to add an extra line or two in your service class to properly translate things.

Introspection in Flash Builder

This is the key to working with Flash apps.  Flash Builder allows Flash developers to call remote objects and place the results in a native Flash object. Flash Builder can take a look at the return value of a remote call and automatically create a native object based off of that.  This is really great for POPOs, but…

Not as good for Zend_Db objects

But don't let that fool you into thinking that it's problematic.  Before I tell you why, let's go over some of the issues when you use a Zend_Db object.

Problem #1: The AMF Serializer does not properly serialize Zend_Db_Table_Row_Abstract objects as of ZF 1.10.4.  This will be changed in 1.10.5 with a very simple fix.  In fact, it's possible that by the time you're reading this it may not be an issue any more.

The reason for this is that the AMF serializer does a foreach loop over the objects that it's going to be serializing to write each property to the wire. What this does for a POPO (fun to say, isn't it?) is that it iterates over publicly defined properties of the object.  However, with a Zend_Db row object the data is stored in a protected array and not iterate-able.  The data does not have public accessibility. The change to make introspection work from front-end to backend is done by having the Zend_Db_Table_Row_Abstract class also implement IteratorAggregate and return the value of $this->_data.  Once this has been completed there will be front-to-back introspection.

Problem #2: New Zend_Db objects are not created using a constructor.  They are created by calling fetchNew() on a DB table object. But the AMF serializer will create the object using the contructor. The problem here is that when you try to save a Zend_Db_Table_Row_Abstract based object the table object will not have been defined.  The way around this is to actually use one of the hooks in the row class called init().

protected $_tableClass = 'Model_DbTable_Census';

public function init()
{
    if ($this->_getTable() == null) {
        $this->setTable(new $this->_tableClass());
    }
}

What this does is check to see if the table has been defined.  If it has not, the individual row object will create one for itself.  This could also technically be done in an overarching manner with an abstract model definition to handle it.

One question you might have is "whose fault is this?" Is it Zend_Db or Zend_Amf?  The actual answer is neither.  Both are operating fine within their own patterns.  What this is is a discongruency of patterns.  And so we need to handle that with the code in the init.  The other caveat is that with this functionality you cannot have a direct call to the save() method for both create and update operations.  For one of them you will need to get an instance of the class in the service object prior to calling the save operations.  In my third part of this series I will show you what I mean.

Using a service object

While it might seem reasonable to simply provide direct access to your individual models there are actually two reasons why this will not work or is not a good idea.

1) Flash Builder requires your data model class files to be located in the document root.  This does not work well with a proper Zend Framework application

2) Dependencies will be difficult to manage.  In other words, directly calling a class called User may work fine but any additional data, such as permissions, should have its logic defined on the server side.  Otherwise it will be waaayyy too easy to hack. 

Having a service object allows you to put a very thin class in the document root so Flash Builder can introspect it (I'm hoping this requirement will be removed at a later date) and it also limits the damage that an end user can do.

Conclusion

Having seen some of these issues am I concerned at all about integrating a native Flash and a native ZF application?  Not really.  Understanding the reasons why some of the problems existed took a little bit of time, however the implementations are actually really easy.  There was one bug and it will be fixed in ZF 1.10.5 with about 3 lines of code.  So all in all, now that I'm over the hurdle I am really looking forward to doing more ZF work with AMF and Flash.

Downloads.  Everyone wants downloads.  Once I have finished the third part of this series I will be making the fully functional application available for download as a Zend Studio/PDT project.

Leave a Reply

Your email address will not be published. Required fields are marked *