apache-flexobjecttypesamfphpzend-amf

AMF typed objects from flex back to PHP


Yesterday, I succeeded in sending typed objects from a PHP application to a flex front-end using Zend_AMF as per this question.

The problem I am facing now is that I would like to send a typed object from flex to PHP and on the PHP side, be able to recieve it as a typed object instead of stdClass.

Here is the class in flex:

package com.mysite
{
    [Bindable]
    [RemoteClass(alias="CTest")]
    public class CTest
    {

        public var stuff1:String;

        public var stuff2:String;

        public function CTest()
        {
        }
    }
}

And this is the corresponding class in PHP:

<?php
namespace modules\testing;

class CTest{

    var $_explicitType = 'CTest';

    var $stuff1;

    var $stuff2;
}

In flex, I am sending the object like so:

var remoteObject:RemoteObject = new RemoteObject(); 
remoteObject.endpoint = "http://localhost/to/my/amf/endpoint"; 
remoteObject.showBusyCursor = true; 
remoteObject.source = 'testing'; 
var op:AbstractOperation = remoteObject.getOperation(null); 
op.addEventListener(ResultEvent.RESULT, result); 
op.send( new CTest()); 

On the PHP side, the object is retrieved into a variable called $parameters. I then use print_r on it to write the result to a file:

$z = print_r($parameters, true);
$s = fopen('D:\test.txt', 'w+');
fwrite($s, $z);
fclose($s);

And as can be seen, the result comes back untyped and is a stdClass object:]

Array
(
    [0] => stdClass Object
        (
            [stuff1] => 
            [stuff2] => 
        )

)

After some testing, I removed the namespace from the PHP object and moved it into the global namespace. This seems to have resolved the issue. I have tried setting RemoteClass to \modules\testing\CTest and also modules.testing.CTest. $_eplicitType was then set to the same value for both tests.

The result is that when I use modules.testing.CTest, this is the classname that Zend_AMF sees. If I use namespace notation, Zend_AMF sees modulestestingCTest, as all the slashes get stripped out.

But how can I get this working with php namespaces?


Solution

  • Finally resolved the issue. Here is the solution for those who might come across the same issue in the future.

    For your PHP class:

    <?php
    namespace app\testing;
    class CTest{
    
        var $_explicitType = 'app\testing\CTest';
    
        var $stuff1;
    
        var $stuff2;
    }
    

    For your actionscript class:

    package com.mysite
    {
        [Bindable]
        [RemoteClass(alias="app\\\\testing\\\\CTest")]
        public class CTest
        {
    
            public var stuff1:String;
    
            public var stuff2:String;
    
            public function CTest()
            {
            }
        }
    }
    

    I think the problem is due to the serialization and deserialization of the AMF body. Effectively, the remote class is has 2 slashes escaped, resulting in this: app\\testing\\CTest. Once it is deserialzed by Zend_AMF, since there are 2 slashes, it means that the backslashes are escaped into this: app\testing\CTest. This is just a hunch of course, but some testing with Charles proved that this is the case.

    Another possible solution is to modify Zend_Amf_Parse_TypeLoader.php. On line 99, we could replace:

     if(!$class) {
                $class = str_replace('.', '_', $className);
      }
    

    with

    if(!$class) {
         $class = str_replace('.', '\\', $className);
    }
    

    Effectively, we can then just use dot syntax for the class mappings, which actionscript will place nicely with:

    [RemoteClass(alias="app.testing.CTest")]
    
    var $_explicitType = 'app.testing.CTest';
    

    Obviously this will is a pretty nice solution, but I prefer not to modify with vendor code, as the Zend_AMF library will be updated with newer versions in the future. For now, my solution is to just use 4 slashes.