所以我目前正在尝试使用 PHP SoapClient 实现外部 API 调用- 我发现它的工作方式非常奇怪。
假设我有以下 WSDL 定义:
<xs:element name="someParamList">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="someParam" type="someParam"/>
</xs:sequence>
</xs:complexType>
</xs:element>
可能会返回:
<someParamList>
<someParam>foo</someParam>
<someParam>bar</someParam>
</someParamList>
或者:
<someParamList>
<someParam>foo</someParam>
</someParamList>
我已将 someParamList 映射到 SomeParamListClass
使用 classmap
属性将 someParam 转换为 SomeParamClass
。一般来说,这工作得很好,但是取决于结果,我并不总是得到SomeParamClass
的数组
。如果列表中只有 1 个结果,PHP 将直接设置对象而不是包含单个对象的数组。
我尝试在 __construct
__set
或普通 setter 中转换数据,但都没有被调用。
所以: 为什么 SoapClient 的行为如此奇怪,为什么它从不调用构造函数或 setter ? 如何获得一致的列表?
最佳答案
与各种反序列化例程一样,SoapClient 不会将值传递给您可以拦截的构造函数或 setter ,它只是使用“神奇”设置的值在内部创建对象。
您可以做的是使用 typemap
选项而不是 classmap
,它允许您分配用于转换类型的回调,而不是类名。
但是,使用 $options
参数可以更轻松地绕过“智能”列表格式:
features
option is a bitmask of ... SOAP_SINGLE_ELEMENT_ARRAYS ...
这并没有在任何地方得到真正的描述,但它强制解码后的 XML 的每个元素都是一个数组,而不是试图猜测哪些是单个元素,哪些是多个元素。这可能意味着您必须编写很多 $response[0]['foo'][0]['bar'][0]
,但至少它是可以预测的。
所以:
$client = new SoapClient(
$wsdl,
[
// other options which you're already passing here...
'features' => SOAP_SINGLE_ELEMENT_ARRAYS
]
);
关于php - PHP SOAP 类转换如何工作以及如何获得一致的列表结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52588989/