将自定义类型对象作为 PHP 服务方法调用的参数传递
我们使用 zendamf 作为 Flex 客户端和 PHP 服务器之间的远程网关。 将服务器端类型映射到客户端类型似乎对作为服务方法参数传递的对象没有任何影响。 所有具有自定义类型的对象都作为 stdClass 实例接收。 有没有办法强制这个?或者我们在这里遗漏了什么?
有什么想法吗?
谢谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个问题有点老了,但还没有答案。那么让我尝试一下。 ;)
首先@www.Flextras.com:
你是对的。在 PHP 中,还需要进行一些类映射工作。
因此,对于所有对如何使用 Zend Framework 定义类映射感兴趣的人,请看一下下面简短但(在我看来)详细的介绍。如果您知道所有这些,那么请跳过介绍并继续“关于 Zend Framework 中的客户端到服务器映射和 stdClass”
使用 Zend Framework 在 PHP 中进行类映射的方式
正如 Zend Framework 的 Zend_Amf_Server 的文档所描述的,您有 3 个选项提供类映射。您可以在此处找到完整文档(位于页面中间的某个位置) “类型化对象”)。
第一个选项
这是最灵活的选项,因为您可以显式指定客户端到服务器和服务器到客户端两个方向的类映射。与灵活性相反,你可能会在这里犯更多错误。您将在下面找到使用类映射时要考虑的事项的清单。
第二个选项
这样做你的类映射会变得更加动态,因为 Zend_Amf_Server 将自动搜索
$_explicitType
属性。因此,您不必像第一个选项那样显式定义类映射。不幸的是,使用$_explicitType
您无法为映射定义 PHP 类名(这是“更动态”)。再往下您将找到有关此处提出的问题的详细描述。第三个选项
通过使用最后一个选项,您将获得最动态的类映射。您可以像我的示例一样简单地返回字符串文字,但这与使用
$_explicitType
选项相同。该方法的优点是让类动态生成 ActionScript 类名。因此,您可以在所有 AMF 类继承的层次结构中最顶层的类上定义getASClassName()
。这里的缺点与第二个选项相同。您无法定义该类映射到的 PHP 类名。
Flex 和 Zend Framework 的类映射清单
如果您在指定类映射时出现错误,Flex 将无法转换为强类型对象。相反,您将获得通用
Object
类的实例。如果发生这种情况,您应该检查是否存在以下一种或多种情况。在 Flex 方面,
[RemoteClass]
元数据标记。[RemoteClass(alias="")]
) 指定远程类,请检查您是否输入错误。public var ...
或 getter/setter 对)[Transient]
元数据标记标记了不用于传输的属性? (这将排除如此标记的属性被序列化/反序列化)在 Zend Framework 方面,
[RemoteClass]
标记中定义的完全相同)关于 Zend Framework 中的客户端到服务器映射和 stdClass
我还遇到了以下问题:强类型参数传递给服务器端的服务类方法,生成
stdClass
。我经常试图找出为什么会发生这种情况,但从未花时间真正找到原因。昨天,在我的一个项目中再次尝试使类映射尽可能动态/通用之后,经过几个小时的研究,我发现 Zend_Amf_Server 在收到 AMF 请求时会做什么。 (顺便说一句:如果我没有在我的 PHP 代码中实现严格的类命名约定,我永远不会找到原因)。当 AMF 请求传入并且 Zend_Amf_Server 开始解析它时,它将从请求中读取某个远程类别名并尝试自动加载该类。这就是我们想要 Zend_Amf_Server 做的事情,对吧!?但 AMF 服务器仅支持自动处理类名(如
MyClassName
)或符合框架的命名约定(如My_Class_Name
)。您无法使用远程类别名(如 com.company.SomeAmfClass )自动映射类。 Zend 期望您指定一个包(代表普通目录路径),并在尝试加载该类之前将所有句点转换为下划线。执行此操作的类是Zend_Amf_Parse_TypeLoader
。 AMF 服务器将调用其静态方法loadType()
。下面是该方法的实现(直接从 Zend Framework 1.11.7 复制):
首先,我尝试定义一个实现
Zend_Loader_Autoloader_Interface
的类,并将其推送到Zend_Loader_Autoloader
singleton 的自动加载器堆栈。但这里的问题是Zend_Amf_Parse_TypeLoader::loadType()
在自动加载发生之前修改了类名 - 调用class_exists()
时会发生什么。因此,您可以做的就是直接在框架中更改该方法,以另一种方式处理
com.company.SomeAmfClass
等 ActionScript 类名。但这应该是最后一个选择,因为更改框架代码是不好的做法!另一个解决方案 - 几乎是最干净的 - 是重新组织和重命名所有类以适应 Zend Framework 的命名约定,但不幸的是,这可能需要数小时的重构(这在 PHP 中并不容易处理),并且可能需要数天的测试和测试调试整个代码库。
为了取得平衡,您可以对所需的框架类进行猴子修补。因此,您不会更改框架本身,但也不会重构您的代码库。有一些框架可以解决这个问题。我在 这个问题的答案中找到了一些
示例这个问题在这里:
AMF 类型对象从 Flex 返回到 PHP
您应该检查它是否符合您的需求。
希望这对某人有帮助。如果我忘记了什么(例如在清单中!),请告诉我
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!)