We're using zendamf as a remoting gateway between a flex client and a PHP server. Mapping server side types to client side types doesn't seem to have any affect on objects passed as service method parameters. All objects that have custom types are received as stdClass instances. Is there a way to force this? Or are we missing someting here?
Any thoughts?
Thx!
A bit older this question but not answered, yet. So let me try. ;)
First @www.Flextras.com: You are right. In PHP it is also necessary to do some class mapping stuff.
So for all of you interested in how to define class mapping by using the Zend Framework, take a look at the following short but (in my opinion) detailed introduction. If you know all that then skip introduction and go ahead with "About client-to-server mapping and stdClass in Zend Framework"
The ways of class mapping in PHP using the Zend Framework
As the documentation of the Zend Framework's Zend_Amf_Server describes you have 3 options to provide class mapping. You can find the full documentation here (somewhere in the middle of the page under "Typed Objects").
First option
This is the most flexible option because you can dictate the class mappings explicitly for both directions client-to-server and server-to-client. In contrast to flexibility you can make more mistakes here. You will find a checklist below what to consider when using class mapping.
Second option
Doing it this way your class mapping becomes a bit more dynamic, because Zend_Amf_Server will search automatically for the
$_explicitType
property. So you do not have to define a class mapping explicitly like in the first option. Unfortunately using the$_explicitType
you cannot define the PHP class name for the mapping (this is the "bit more dynamic"). Further down you will find a detailed description about the problem which raises here.Third option
By using this last option you will get the most dynamics out of class mapping. You can simply return a string literal like in my example, but this would be the same as using the
$_explicitType
option. The advantage of the method approach is to let classes generate the ActionScript class name dynamically. So you could definegetASClassName()
on the top-most class in hierarchy that all your AMF classes inherit from. The drawback here is the same as for the second option. You cannot define the PHP class name the class is mapped to.Class Mapping Checklist for Flex and Zend Framework
If you made something wrong in specifying class mapping, Flex will not be able to convert to strongly typed objects. Instead you will get an instance of the generic
Object
class. If this happens you should check whether one ore more of the following things are the case.On Flex side
[RemoteClass]
metadata tag.[RemoteClass(alias="")]
), then check whether you have made a typing error.public var ...
or a getter/setter pair)[Transient]
metadata tag? (This will exclude the so-marked property from being serialzed/deserialized)On Zend Framework side
[RemoteClass]
tag in your Flex application)About client-to-server mapping and stdClass in Zend Framework
I also ran into the problem that strongly typed arguments passed to service class methods on server side resulting in
stdClass
. I often tried to find out why this happens but never took the time to really find the reason. Yesterday, after an additional attempt to make class mapping as dynamic/generic as possible in one of my projects and after several hours of research I found what Zend_Amf_Server will do when getting an AMF request. (BTW: I had never found the reason if I hadn't implement strict class naming conventions into my PHP code).When the AMF request is coming in and Zend_Amf_Server starts parsing it, it will read the some remote class alias from the request and tries to load that class automatically. That's what we want Zend_Amf_Server to do, right!? But the AMF server supports only automatisms for handling class names like
MyClassName
or conform to the framework's naming conventions something likeMy_Class_Name
. You cannot map automatically classes with a remote class alias likecom.company.SomeAmfClass
. Zend expects that you specified a package (what represents an ordinary directory path) and converts all the periods to underscores before making an attempt to load the class. The class that will do this stuff isZend_Amf_Parse_TypeLoader
. The AMF server will call the static methodloadType()
on it.Here's the implementation of that method (copied directly out of Zend Framework 1.11.7):
First I've tried to define a class that implements
Zend_Loader_Autoloader_Interface
and pushed it onto theZend_Loader_Autoloader
singleton's autoloader stack. But the problem here was thatZend_Amf_Parse_TypeLoader::loadType()
modifies the class name before autoloading takes place - what happens whenclass_exists()
is invoked.So what you could do is to change that method directly in the framework to handle ActionScript class names like
com.company.SomeAmfClass
in an additional way. But this should be the very last option, because its bad practice to change framework code!Another solution - and almost the cleanest - would be to reorganize and rename all your classes to fit into the Zend Framework's naming conventions, but unfortunately this may take hours of refactoring (what's not really easy to handle in PHP) and maybe days of testing and debugging your whole codebase.
To strike a balance you could monkey-patch the required framework classes. So you would not change the framework itself but do not refactor your codebase. There are some frameworks that will do the trick. I found some examples in the answers of this question
Additionally found this question here: AMF typed objects from flex back to PHP You should check whether it fits your needs.
Hope this will be helpful to someone. Tell me if I forgot something (for example in the checklist!)