所以我目前正在尝试使用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
和使用SomeParamClass
属性的classmap
的someParam。一般来说,此方法效果很好,但但是取决于结果,我并非总是能得到array
中的SomeParamClass
。如果列表中只有1个结果,则PHP将直接设置对象,而不是其中包含单个对象的数组。
我尝试用__construct
__set
或普通的setter来转换数据,但是没有一个被调用。
所以: 为什么SoapClient的行为如此怪异,为什么它从不调用构造函数或setter? 以及如何获得一致的列表?
答案 0 :(得分:1)
与各种反序列化例程一样,SoapClient不会将值传递给您可以拦截的构造函数或设置器,它只是在内部创建了具有“神奇”设置值的对象。
相反,您可以使用typemap
选项而不是classmap
,它使您可以分配用于转换类型而不是类名的回调。
但是,使用$options
参数可以更轻松地绕过“智能”列表格式:
features
选项是... 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
]
);