这个问题有点老了,但还没有回答。所以让我试试。 ;)
首先@www.Flextras.com:
你说的对。在 PHP 中,还需要做一些类映射。
因此,对于所有对如何使用 Zend 框架定义类映射感兴趣的人,请查看以下简短但(在我看来)详细的介绍。如果您了解所有这些,请跳过介绍,继续阅读“关于 Zend 框架中的客户端到服务器映射和 stdClass”
使用 Zend 框架在 PHP 中进行类映射的方式
正如 Zend Framework 的 Zend_Amf_Server 的文档所描述的,您有 3 个选项来提供类映射。你可以找到完整的文档here (somewhere in the middle of the page under "Typed Objects")。
第一个选项
// Use the setClassMap() method of Zend_Amf_Server
require_once '<PathToZendFramework>/Zend/Amf/Server.php';
$server = new Zend_Amf_Server();
$server->setClassMap('MyActionScriptClassName', 'MyPHPClassName');
// the typical package notation for ActionScript class names is also allowed here
$server->setClassMap('com.company.MyActionScriptClassName', 'MyPHPClassName');
这是最灵活的选项,因为您可以为客户端到服务器和服务器到客户端两个方向明确指定类映射。与灵活性相比,您可以在此处犯更多错误。您将在下面找到使用类映射时需要考虑的清单。
第二个选项
// Define a special named public property on each class used for
// serialization/deserialization via AMF
public class MyPHPClassName
{
public $_explicitType = 'MyActionScriptClassName';
/* your class definition here */
}
这样做,您的类映射变得更加动态,因为 Zend_Amf_Server 将自动搜索 $_explicitType 属性。因此,您不必像第一个选项那样明确定义类映射。不幸的是,使用 $_explicitType 您无法为映射定义 PHP 类名(这是“更动态一点”)。再往下,您将找到有关此处提出的问题的详细说明。
第三个选项
// Define a special named public method on each class used for
// serialization/deserialization via AMF
public class MyPHPClassName
{
public function getASClassName()
{
return 'MyActionScriptClassName';
}
/* your class definition here */
}
通过使用最后一个选项,您将从类映射中获得最大的动态。您可以像我的示例一样简单地返回字符串文字,但这与使用 $_explicitType 选项相同。方法方法的优点是让类动态生成 ActionScript 类名。因此,您可以在所有 AMF 类继承自的层次结构中最顶层的类上定义 getASClassName()。
这里的缺点与第二个选项相同。您不能定义类映射到的 PHP 类名。
Flex 和 Zend 框架的类映射清单
如果您在指定类映射时出错,Flex 将无法转换为强类型对象。相反,您将获得通用 Object 类的实例。如果发生这种情况,您应该检查是否存在以下一种或多种情况。
在 Flex 侧
- 您的班级必须有一个
[RemoteClass] 元数据标签。
- 如果您使用别名 (
[RemoteClass(alias="")]) 指定远程类,请检查您是否输入错误。
- 您的类(包括它继承自的所有类)是否定义了在服务器端等效项上定义的所有公共属性? (可以是
public var ... 或 getter/setter 对)
- 您是否将公共属性定义为读写?
- 您是否使用
[Transient] 元数据标签标记了不用于传输的属性? (这将排除如此标记的属性被序列化/反序列化)
在 Zend 框架方面
- 您是否使用了类映射的三个选项之一?
- 如果您使用第一个选项,那么您是否错误地输入了 ActionScript 或 PHP 类名? (ActionScript 类名必须与 Flex 应用程序中
[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 复制而来):
/**
* Load the mapped class type into a callback.
*
* @param string $className
* @return object|false
*/
public static function loadType($className)
{
$class = self::getMappedClassName($className);
if(!$class) {
$class = str_replace('.', '_', $className);
}
if (!class_exists($class)) {
return "stdClass";
}
return $class;
}
首先,我尝试定义一个实现Zend_Loader_Autoloader_Interface 的类并将其推送到Zend_Loader_Autoloader 单例的自动加载器堆栈中。但是这里的问题是Zend_Amf_Parse_TypeLoader::loadType() 在自动加载发生之前修改了类名——当class_exists() 被调用时会发生什么。
因此,您可以做的是直接在框架中更改该方法,以另一种方式处理像 com.company.SomeAmfClass 这样的 ActionScript 类名称。但这应该是最后的选择,因为更改框架代码是不好的做法!
另一种解决方案 - 几乎是最干净的 - 是重新组织和重命名所有类以适应 Zend 框架的命名约定,但不幸的是,这可能需要数小时的重构(这在 PHP 中并不容易处理)甚至数天测试和调试你的整个代码库。
为了取得平衡,您可以对所需的框架类进行猴子补丁。因此,您不会更改框架本身,但也不会重构您的代码库。有一些框架可以解决问题。我在this question的回答中找到了一些例子
另外在这里发现了这个问题:
AMF typed objects from flex back to PHP
您应该检查它是否符合您的需求。
希望这对某人有所帮助。如果我忘记了什么(例如在清单中!),请告诉我!