我正在用php测试一些Soap功能
$soapClient = new CustomSoapClient($urlWsdl,[
'exceptions' => true
'trace' => true,
'location' => $soapUrl
]);
$soapResponse = $soapClient->__call('ProfileLookup',$methodArgs)
CustomSoapClient是一个类,它扩展了基本的SoapClient类,以便记录xml请求和响应(在"__doRequest"方法中)。$soapUrl是测试Soap服务器的位置,它能够通过返回一个或多个结果来回答profilellookup方法
wsdl ($urlWsdl)定义此方法及其返回类型
<wsdl:operation name="ProfileLookup">
<wsdl:input message="tns:ProfileLookupRequest"/>
<wsdl:output message="tns:ProfileLookupResponse"/>
</wsdl:operation>
<wsdl:message name="ProfileLookupResponse">
<wsdl:part name="LookupResponse" element="n:LookupResponse"/>
</wsdl:message>
<xs:element name="LookupResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="Result" type="c:ResultStatus"/>
<xs:element name="ProfileLookups" type="tns:ProfileLookupList"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="ProfileLookup">
<xs:sequence>
<xs:element name="PersonName" type="c:PersonName"/>
...
</xs:sequence>
</xs:complexType>
<xs:complexType name="ProfileLookupList">
<xs:sequence>
<xs:element name="ProfileLookup" type="tns:ProfileLookup" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
如果我调用我的Web服务,这个返回多个结果,返回的xml是OK
<env:Body>
<ns1:LookupResponse>
<ns1:Result resultStatusFlag="SUCCESS"/>
<ns1:ProfileLookups>
<ns1:ProfileLookup>
<ns1:PersonName>
</ns1:PersonName>
</ns1:ProfileLookup>
<ns1:ProfileLookup>
<ns1:PersonName>
</ns1:PersonName>
</ns1:ProfileLookup>
</ns1:ProfileLookups>
</ns1:LookupResponse>
</env:Body>
,这是php中响应的转换方式
[ProfileLookups] => stdClass Object (
[ProfileLookup] => Array(
[0] => stdClass Object (
[PersonName] => stdClass Object()
),
[1] => stdClass Object (
[PersonName] => stdClass Object()
)
)
)
如果我调用web服务只是为了得到一个结果我得到相同的xml结构
<env:Body>
<ns1:LookupResponse>
<ns1:Result resultStatusFlag="SUCCESS"/>
<ns1:ProfileLookups>
<ns1:ProfileLookup>
<ns1:PersonName>
</ns1:PersonName>
</ns1:ProfileLookup>
</ns1:ProfileLookups>
</ns1:LookupResponse>
</env:Body>
但是转换为php值是不同的:
[ProfileLookups] => stdClass Object (
[ProfileLookup] => stdClass Object(
[PersonName] => stdClass Object()
)
)
如你所见,在第一个例子中,profilellookup是一个类型为"profilellookup"的对象数组,在第二个例子中,profilellookup本身是一个类型为"profilellookup"的对象。因此,如果只返回一项,下面的代码将导致错误。
foreach($soapResponse->ProfileLookups->ProfileLookup as $profileLookup){
echo $profileLookup->PersonName->...
}
当然,我可以很容易地测试ProfileLookups-> profilellookup是一个数组还是一个对象,然后强制它是一个数组。但这似乎不是正确的方法,因为我可能在应用程序的每个部分都面临这个问题。
控制SoapClient将xml转换为php值的方式的解决方案是什么?自己解析xml响应会更好吗?像Zend'Soap这样的库能在这个用例中提供帮助吗?我在哪里可以找到SoapClient转换xml到php值的方式的参考文档?
解决方案是在创建SoapClient
时启用SOAP_SINGLE_ELEMENT_ARRAYS
特性:
$client = new SoapClient($wsdl, array(
'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
));
我强烈建议您使用WSDL到php生成器,这样您将始终得到您期望的类型的php对象,或者如果您应该得到数组,则得到数组。您应该尝试PackageGenerator项目。